#include "HY1C_out.h"
#include "l12_proto.h"
#include "config.h"
#include <string.h>
#include <clo.h>

#include <assert.h>
#include <strings.h>

static int32_t numTauas = -1;
static int32_t numGains = -1;
static int32_t numGainUncs = -1;
static int32_t numOffsets = -1;

static int enableFileDecending = 1;

int defnaermodels = 80;
// debug for COCTS aertab and La
char defaermodels[][32] = {"r30f95v01", "r30f80v01", "r30f50v01", "r30f30v01", "r30f20v01", "r30f10v01", "r30f05v01", "r30f02v01", "r30f01v01", "r30f00v01",
    "r50f95v01", "r50f80v01", "r50f50v01", "r50f30v01", "r50f20v01", "r50f10v01", "r50f05v01", "r50f02v01", "r50f01v01", "r50f00v01",
    "r70f95v01", "r70f80v01", "r70f50v01", "r70f30v01", "r70f20v01", "r70f10v01", "r70f05v01", "r70f02v01", "r70f01v01", "r70f00v01",
    "r75f95v01", "r75f80v01", "r75f50v01", "r75f30v01", "r75f20v01", "r75f10v01", "r75f05v01", "r75f02v01", "r75f01v01", "r75f00v01",
    "r80f95v01", "r80f80v01", "r80f50v01", "r80f30v01", "r80f20v01", "r80f10v01", "r80f05v01", "r80f02v01", "r80f01v01", "r80f00v01",
    "r85f95v01", "r85f80v01", "r85f50v01", "r85f30v01", "r85f20v01", "r85f10v01", "r85f05v01", "r85f02v01", "r85f01v01", "r85f00v01",
    "r90f95v01", "r90f80v01", "r90f50v01", "r90f30v01", "r90f20v01", "r90f10v01", "r90f05v01", "r90f02v01", "r90f01v01", "r90f00v01",
    "r95f95v01", "r95f80v01", "r95f50v01", "r95f30v01", "r95f20v01", "r95f10v01", "r95f05v01", "r95f02v01", "r95f01v01", "r95f00v01"};


//char defaermodels[][32] = {"r30f95", "r30f80", "r30f50", "r30f30", "r30f20", "r30f10", "r30f05", "r30f02", "r30f01", "r30f00",
//    "r50f95", "r50f80", "r50f50", "r50f30", "r50f20", "r50f10", "r50f05", "r50f02", "r50f01", "r50f00",
//    "r70f95", "r70f80", "r70f50", "r70f30", "r70f20", "r70f10", "r70f05", "r70f02", "r70f01", "r70f00",
//    "r75f95", "r75f80", "r75f50", "r75f30", "r75f20", "r75f10", "r75f05", "r75f02", "r75f01", "r75f00",
//    "r80f95", "r80f80", "r80f50", "r80f30", "r80f20", "r80f10", "r80f05", "r80f02", "r80f01", "r80f00",
//    "r85f95", "r85f80", "r85f50", "r85f30", "r85f20", "r85f10", "r85f05", "r85f02", "r85f01", "r85f00",
//    "r90f95", "r90f80", "r90f50", "r90f30", "r90f20", "r90f10", "r90f05", "r90f02", "r90f01", "r90f00",
//    "r95f95", "r95f80", "r95f50", "r95f30", "r95f20", "r95f10", "r95f05", "r95f02", "r95f01", "r95f00"};



// need a place to store the default product lists
static char default_l2prod[MAX_OFILES][PRODSTRLEN];

static char default_flaguse[1024];

// store the name of program we are running.
static char mainProgramName[50];

static char *l2gen_optionKeys[] = {
    "-help",
    "-version",
    "-dump_options",
    "-dump_options_paramfile",
    "-dump_options_xmlfile",
    "par",
    "pversion",
    "suite",
    "eval",
    "ifile",
    "ilist",
    "geofile",
    "ofile",
    "fmtofile",
    "il2file",
    "tgtfile",
    "aerfile",
    "metafile",
    "l2prod",
    "spixl",
    "epixl",
    "dpixl",
    "sline",
    "eline",
    "dline",
    "ctl_pt_incr",
    "proc_ocean",
    "proc_land",
    "proc_sst",
    "atmocor",
    "mode",
    "aer_opt",
    "aer_wave_short",
    "aer_wave_long",
    "aer_swir_short",
    "aer_swir_long",
    "aer_rrs_short",
    "aer_rrs_long",
    "aermodmin",
    "aermodmax",
    "aermodrat",
    "aer_angstrom",
    "aer_iter_max",
    "mumm_alpha",
    "mumm_gamma",
    "mumm_epsilon",
    "degc",
    "absaer_opt",
    "glint_opt",
    "outband_opt",
    "oxaband_opt",
    "filter_opt",
    "filter_file",
    "brdf_opt",
    "gas_opt",
    "iop_opt",
    "seawater_opt",
    "polfile",
    "pol_opt",
    "ocrvc_opt",
    "rad_opt",
    "xcalfile",
    "xcal_opt",
    "xcal_wave",
    "resolution",
    "giop_aph_opt",
    "giop_aph_file",
    "giop_aph_s",
    "giop_adg_opt",
    "giop_adg_file",
    "giop_adg_s",
    "giop_bbp_opt",
    "giop_bbp_file",
    "giop_bbp_s",
    "giop_rrs_opt",
    "giop_grd",
    "giop_wave",
    "giop_maxiter",
    "giop_fit_opt",
    "gsm_opt",
    "gsm_fit",
    "gsm_adg_s",
    "gsm_bbp_s",
    "gsm_aphw",
    "gsm_aphs",
    "qaa_adg_s",
    "qaa_wave",
    "chloc2_wave",
    "chloc2_coef",
    "chloc3_wave",
    "chloc3_coef",
    "chloc4_wave",
    "chloc4_coef",
    "chlclark_wave",
    "chlclark_coef",
    "kd2_wave",
    "kd2_coef",
    "flh_offset",
    "sstcoeffile",
    "sstssesfile",
    "sstmirrfile",
    "sst4coeffile",
    "sst4ssesfile",
    "sst4mirrfile",
    "vcnnfile",
    "owtfile",
    "owtchlerrfile",
    "aermodels",
    "met1",
    "met2",
    "met3",
    "ozone1",
    "ozone2",
    "ozone3",
    "land",
    "water",
    "demfile",
    "icefile",
    "ice_threshold",
    "sstfile",
    "no2file",
    "alphafile",
    "tauafile",
    "cldfile",
    "calfile",
    "offset",
    "gain",
    "flaguse",
    "xcalbox",
    "xcalboxcenter",
    "xcalpervalid",
    "xcalsubsmpl",
    "chlthreshold",
    "aotthreshold",
    "coccolith",
    "cirrus_thresh",
    "taua",
    "cloud_thresh",
    "cloud_wave",
    "cloud_eps",
    "glint_thresh",
    "absaer",
    "rhoamin",
    "sunzen",
    "satzen",
    "epsmin",
    "epsmax",
    "tauamax",
    "nLwmin",
    "hipol",
    "wsmax",
    "windspeed",
    "windangle",
    "pressure",
    "ozone",
    "relhumid",
    "watervapor",
    "maskland",
    "maskbath",
    "maskcloud",
    "maskglint",
    "masksunzen",
    "masksatzen",
    "maskhilt",
    "maskstlight",
    "sl_frac",
    "sl_pixl",
    "vcal_opt",
    "vcal_chl",
    "vcal_solz",
    "vcal_nLw",
    "vcal_Lw",
    "owmcfile",
    "north",
    "south",
    "east",
    "west",
    "xbox",
    "ybox",
    "subsamp",
    "prodxmlfile",
    NULL
};

static char *l1bgen_optionKeys[] = {
    "-help",
    "-version",
    "-dump_options",
    "-dump_options_paramfile",
    "-dump_options_xmlfile",
    "par",
    "pversion",
    "suite",
    "ifile",
    "ofile",
    "spixl",
    "epixl",
    "sline",
    "eline",
    "calfile",
    "xcalfile",
    "gain",
    "offset",
    "sl_pixl",
    "sl_frac",
    NULL
};

static char *vcaltarget_optionKeys[] = {
    "-help",
    "-version",
    "-dump_options",
    "-dump_options_paramfile",
    "-dump_options_xmlfile",
    "par",
    "pversion",
    "suite",
    "ifile",
    "help_ifile",
    "ofile",
    "geofile",
    "il2file",
    "tgtfile",
    "aerfile",
    "spixl",
    "epixl",
    "sline",
    "eline",
    "chlthreshold",
    "aotthreshold",
    "flaguse",
    "maxpointdist",
    "vct_msk_water",
    "vct_water",
    "vct_min_nbin",
    "vct_fill_pct",
    NULL
};

static char *l1mapgen_optionKeys[] = {
    "-help",
    "-version",
    "-dump_options",
    "-dump_options_paramfile",
    "-dump_options_xmlfile",
    "par",
    "pversion",
    "suite",
    "ifile",
    "geofile",
    "resolution",
    "ofile",
    "north",
    "south",
    "east",
    "west",
    "width",
    "threshold",
    "rgb",
    "atmocor",
    "datamin",
    "datamax",
    "stype",
    "outmode",
    "help_true_color",
    NULL
};

static char *l1brsgen_optionKeys[] = {
    "-help",
    "-version",
    "-dump_options",
    "-dump_options_paramfile",
    "-dump_options_xmlfile",
    "par",
    "pversion",
    "suite",
    "ifile",
    "geofile",
    "resolution",
    "ofile",
    "spixl",
    "epixl",
    "sline",
    "eline",
    "subsamp",
    "rgb",
    "atmocor",
    "datamin",
    "datamax",
    "stype",
    "outmode",
    "help_true_color",
    NULL
};

/*-----------------------------------------------------------------------------
    Function:  msl12_input_init

    Returns:   int (status)
        The return code is a negative value if any error occurs, otherwise,
        returns 0.

    Description:
        Set default values for input structure.

    Parameters: (in calling order)
        Type      Name         I/O   Description
        ----      ----         ---   -----------
        instr     input     O   structure variable for inputs

----------------------------------------------------------------------------*/

void msl12_input_init(instr *input) {
    int i;

    /*                                                                  */
    /* Set input values to defaults                                     */
    /*                                                                  */
    input->mode = FORWARD;
    input->sensorID = -1;
    input->subsensorID = -1;
    input->format = -1;
    input->modis_subset_compat = 0;

    for (i = 0; i < MAX_IFILES; i++)
        input->ifile[i][0] = '\0';

    for (i = 0; i < MAX_OFILES; i++) {
        input->ofile [i][0] = '\0';
        input->fmtofile [i][0] = '\0';
        input->l2prod [i][0] = '\0';
        input->def_l2prod[i][0] = '\0';
        input->il2file [i][0] = '\0';
    }
    input->ilist [0] = '\0';
    input->calfile [0] = '\0';
    input->xcalfile [0] = '\0';
    input->polfile [0] = '\0';
    input->cldfile [0] = '\0';
    input->geofile [0] = '\0';
    input->filter_file [0] = '\0';
    input->tgtfile [0] = '\0';
    input->aerfile [0] = '\0';
    input->metafile [0] = '\0';
    input->vcnnfile [0] = '\0';
    input->owtfile [0] = '\0';
    input->owtchlerrfile [0] = '\0';
    input->aerbinfile [0] = '\0';
    input->owmcfile [0] = '\0';
    input->prodXMLfile [0] = '\0';
    input->btfile [0] = '\0';
    input->sstcoeffile [0] = '\0';
    input->sstssesfile [0] = '\0';
    input->sstmirrfile [0] = '\0';
    input->sst4coeffile [0] = '\0';
    input->sst4ssesfile [0] = '\0';
    input->sst4mirrfile [0] = '\0';
    for (i = 0; i < FILENAME_MAX; i++)
        input->demfile [i] = '\0';

    input->pro_control[0] = '\0';
    input->input_parms[0] = '\0';

    input->naermodels = 0;
    for (i = 0; i < MAXAERMOD; i++)
        input->aermodels[i][0] = '\0';

    input->spixl = 1;
    input->epixl = -1;
    input->dpixl = 1;
    input->sline = 1;
    input->eline = -1;
    input->dline = 1;
    input->ctl_pt_incr = 8;

    input->sl_pixl = -1;
    input->sl_frac = 0.25;

    input->proc_ocean = 1;
    input->proc_sst = -1;
    input->proc_land = 0;
    input->atmocor = 1;
    input->resolution = -1;

    input->glint_opt = 1;
    input->aer_iter_max = 10;
    input->brdf_opt = -1;
    input->gas_opt = 1;
    input->ocrvc_opt = 0;
    input->iop_opt = IOPNONE;
    input->pol_opt = -1;
    input->rad_opt = -1;
    input->absaer_opt = -1;
    input->gsm_opt = 0;
    input->gsm_fit = 0;
    input->gsm_adg_s = 0.02061;
    input->gsm_bbp_s = 1.03373;
    for (i = 0; i < NBANDS; i++) {
        input->gsm_aphw[i] = -1.0;
        input->gsm_aphs[i] = -1.0;
    }

    input->giop_maxiter = -1;
    input->giop_ts_opt = -1;
    input->giop_fit_opt = -1;
    input->giop_aph_opt = -1;
    input->giop_adg_opt = -1;
    input->giop_bbp_opt = -1;
    input->giop_rrs_opt = -1;
    input->giop_aph_s = -1000.0;
    input->giop_adg_s = -1000.0;
    input->giop_bbp_s = -1000.0;
    input->giop_aph_w = -1.0;
    input->giop_adg_w = -1.0;
    input->giop_bbp_w = -1.0;
    input->giop_grd[0] = -1000.0;
    input->giop_grd[1] = -1000.0;
    for (i = 0; i < NBANDS; i++) {
        input->giop_wave[i] = -1.0;
        input->giop_rrs_unc[i] = -1.0;
    }

    input->qaa_adg_s = 0.015;

    input->flh_offset = 0.0;

    input->seawater_opt = 0;
    input->aer_opt = 99;
    input->outband_opt = 99;
    input->oxaband_opt = 99;
    input->filter_opt = 99;

    input->aer_wave_short = 765;
    input->aer_wave_long = 865;
    input->aer_swir_short = -1;
    input->aer_swir_long = -1;
    input->aer_rrs_short = -1.0;
    input->aer_rrs_long = -1.0;
    input->aer_angstrom = -999.0;

    input->met1 [0] = '\0';
    input->met2 [0] = '\0';
    input->met3 [0] = '\0';
    input->ozone1[0] = '\0';
    input->ozone2[0] = '\0';
    input->ozone3[0] = '\0';
    input->land [0] = '\0';
    input->water [0] = '\0';

    for (i = 0; i < NBANDS; i++) {
        input->gain[i] = 1.0;
        input->gain_unc[i] = 0.0;
        input->offset[i] = 0.0;
        input->taua[i] = 0.0;
        input->vcal_nLw[i] = 0.0;
        input->vcal_Lw[i] = 0.0;
        input->xcal_wave[i] = -1;
        input->xcal_opt[i] = 0;
    }
    input->xcal_nwave = 0;

    input->vcal_chl = -1.0;
    input->vcal_solz = -1.0;
    input->vcal_opt = -1;

    input->degc = 0;

    input->aermodrat = 0.0;
    input->aermodmin = -1;
    input->aermodmax = -1;

    input->albedo = -1.0;
    input->cloud_wave = 865.0;
    input->cloud_eps = -1.0;
    input->absaer = 0.0;
    input->rhoamin = 0.0001;
    input->glint = 0.005;
    input->sunzen = 75.0;
    input->satzen = 60.0;
    input->epsmin = 0.85;
    input->epsmax = 1.35;
    input->tauamax = 0.30;
    input->nlwmin = 0.15;
    input->hipol = 0.50;
    input->wsmax = 8.0;

    input->mumm_alpha = 1.72;
    input->mumm_gamma = 1.00;
    input->mumm_epsilon = 1.00;

    input->windspeed = -1000;
    input->windangle = -1000;
    input->pressure = -1000;
    input->ozone = -1000;
    input->relhumid = -1000;
    input->watervapor = -1000;
    input->ice_threshold = 0.1;

    input->landmask = 1;
    input->bathmask = 0;
    input->cloudmask = 1;
    input->glintmask = 0;
    input->sunzenmask = 0;
    input->satzenmask = 0;
    input->hiltmask = 1;
    input->stlightmask = 1;

    for (i = 0; i < 8; i++) input->coccolith[0] = 0.0;
    for (i = 0; i < 2; i++) input->cirrus_thresh[i] = -1;
    for (i = 0; i < 2; i++) input->chloc2w [i] = -1;
    memset(input->chloc2c, '\0', sizeof (float) *5);
    for (i = 0; i < 3; i++) input->chloc3w [i] = -1;
    memset(input->chloc3c, '\0', sizeof (float) *5);
    for (i = 0; i < 4; i++) input->chloc4w [i] = -1;
    memset(input->chloc4c, '\0', sizeof (float) *5);
    for (i = 0; i < 3; i++) input->chlclarkw[i] = -1;
    memset(input->chlclarkc, '\0', sizeof (float) *6);
    for (i = 0; i < 2; i++) input->kd2w [i] = -1;
    memset(input->kd2c, '\0', sizeof (float) *6);

    strcpy(input->pversion, "Unspecified");
    strcpy(input->suite, "");

    fctl_init(&(input->fctl));

    /* for inverse (calibration) modes */
    input->chlthreshold = CHL_MAX;
    input->aotthreshold = AOT_MAX;
    input->maxpointdist = 0.0;
    strcpy(default_flaguse, "ATMFAIL,LAND,HIGLINT,HILT,HISATZEN,STRAYLIGHT,CLDICE,COCCOLITH,LOWLW,CHLFAIL,NAVWARN,ABSAER,MAXAERITER,ATMWARN,HISOLZEN,NAVFAIL,SSTFAIL");
    strcpy(input->flaguse, default_flaguse);

    input->xcalbox = 0;
    input->xcalboxcenter[0] = 0;
    input->xcalboxcenter[1] = 0;
    input->xcalpervalid = 0;
    input->xcalsubsmpl = 1;

    input->vct_msk_water = 1;
    input->vct_water[0] = '\0';
    input->vct_min_nbin = 4;
    input->vct_fill_pct = 0.04;

    /* for l1mapgen and l1brsgen */
    input->datamin = 0.01;
    input->datamax = 0.9;
    input->west = -999;
    input->east = -999;
    input->north = -999;
    input->south = -999;
    input->width = 600;
    input->threshold = 0.1;
    input->subsamp = 1;
    input->outmode = 0;
    input->stype = 0;
    for (i = 0; i < 3; i++) {
        input->rgb[i] = 1;
    }
    input->xbox = -1;
    input->ybox = -1;

    return;
}

//-----------------------------------------------------------------------

/** CLO callback function for the "par" option.  Loads the parameter file
 into the list that is stored in option->cb_data */
void par_option_cb(struct clo_option_t *option) {
    if (enableFileDecending)
        clo_readFile((clo_optionList_t*) option->cb_data, option->valStr);
}

//-----------------------------------------------------------------------

/** add all of the accepted command line options to list */
int l2gen_init_options(clo_optionList_t* list, char* prog) {
    char tmpStr[2048];
    char tmpStr1[2048];
    char tmpStr2[32];
    clo_option_t* option;
    int i;

    // set the min program name
    strcpy(mainProgramName, prog);
    
    if (!strcmp(prog, "msl12")) {
        clo_setSelectOptionKeys(l2gen_optionKeys);
    } else if (!strcmp(prog, "l2gen")) {
        clo_setSelectOptionKeys(l2gen_optionKeys);
    } else if (!strcmp(prog, "l3gen")) {
        clo_setSelectOptionKeys(l2gen_optionKeys);
    } else if (!strcmp(prog, "l1bgen")) {
        clo_setSelectOptionKeys(l1bgen_optionKeys);
    } else if (!strcmp(prog, "vcaltarget")) {
        clo_setSelectOptionKeys(vcaltarget_optionKeys);
    } else if (!strcmp(prog, "l1mapgen")) {
        clo_setSelectOptionKeys(l1mapgen_optionKeys);
    } else if (!strcmp(prog, "l1brsgen")) {
        clo_setSelectOptionKeys(l1brsgen_optionKeys);
    }

    sprintf(tmpStr, "%s %s (%s %s)", prog, VERSION, __DATE__, __TIME__);
    clo_setVersion(tmpStr);
    clo_addXmlProgramMetadata("progressRegex", "Processing scan .+?\\((\\d+) of (\\d+)\\)");

    sprintf(tmpStr, "Usage: %s argument-list\n\n", prog);
    strcat(tmpStr, "  The argument-list is a set of keyword=value pairs. The arguments can\n");
    strcat(tmpStr, "  be specified on the commandline, or put into a parameter file, or the\n");
    strcat(tmpStr, "  two methods can be used together, with commandline over-riding.\n\n");
    strcat(tmpStr, "  return value: 0=OK, 1=error, 110=north,south,east,west does not intersect\n");
    strcat(tmpStr, "  file data.\n\n");
    strcat(tmpStr, "The list of valid keywords follows:\n");
    clo_setHelpStr(tmpStr);

    // add the par option and add the callback function
    option = clo_addOption(list, "par", CLO_TYPE_IFILE, NULL, "input parameter file");
    option->cb_data = (void*) list;
    option->cb = par_option_cb;

    strcpy(tmpStr, "processing version string");
    clo_addOption(list, "pversion", CLO_TYPE_STRING, "Unspecified", tmpStr);

    strcpy(tmpStr, "product suite string for loading\n");
    strcat(tmpStr, "        suite-specific defaults");
    clo_addOption(list, "suite", CLO_TYPE_STRING, "OC", tmpStr);

    strcpy(tmpStr, "evaluation bitmask\n");
    strcat(tmpStr, "          0: standard processing\n");
    strcat(tmpStr, "          1: init to old aerosol models\n");
    strcat(tmpStr, "         16: enables MODIS cirrus mask\n");
    strcat(tmpStr, "         32: use test sensor info file\n");
    strcat(tmpStr, "         64: use test rayleigh tables\n");
    strcat(tmpStr, "        128: use test aerosol tables\n");
    strcat(tmpStr, "        256: use test polarization tables\n");
    strcat(tmpStr, "       1024: mask modis mirror-side 1 (navfail)\n");
    strcat(tmpStr, "       2048: mask modis mirror-side 2 (navfail)\n");
    strcat(tmpStr, "       4096: remove warm tests for SSTref\n");
    strcat(tmpStr, "       8192: use alt sensor info file in eval\n");
    strcat(tmpStr, "      32768: enables spherical path geom for dtran");
    clo_addOption(list, "eval", CLO_TYPE_INT, "0", tmpStr);

    strcpy(tmpStr, "input L1 file name");
    option = clo_addOption(list, "ifile", CLO_TYPE_IFILE, NULL, tmpStr);
    clo_addOptionAlias(option, "ifile1");

    strcpy(tmpStr, "ifile[#]=input L1 file names (1-original and 2-vicarious) to be cross-calibrated\n");
    strcat(tmpStr, "      or input HDF file names containing cross-calibration pixels");
    clo_addOption(list, "help_ifile", CLO_TYPE_HELP, NULL, tmpStr);

    clo_addOption(list, "ilist", CLO_TYPE_IFILE, NULL, "file containing list of input files, one per line");

    strcpy(tmpStr, "input L1 geolocation file name (MODIS only)");
    clo_addOption(list, "geofile", CLO_TYPE_IFILE, NULL, tmpStr);

    strcpy(tmpStr, "output L2 file #1 name,\n");
    strcat(tmpStr, "        output vicarious L1B for inverse mode\n");
    strcat(tmpStr, "   ofile[#] = additional output L2 file name");
    option = clo_addOption(list, "ofile", CLO_TYPE_OFILE, "output", tmpStr);
    clo_addOptionAlias(option, "ofile1");

    clo_addOption(list, "fmtofile", CLO_TYPE_STRING, NULL, "output L2 file format (HDF/NCDF)");

    strcpy(tmpStr, "input L2 file names for sensor to be\n");
    strcat(tmpStr, "        used as a calibrator.  Alternatively, a data point can be used as a\n");
    strcat(tmpStr, "        calibrator (e.g. MOBY)\n");
    strcat(tmpStr, "   il2file[#] = additional L2 calibration file names");
    option = clo_addOption(list, "il2file", CLO_TYPE_IFILE, NULL, tmpStr);
    clo_addOptionAlias(option, "il2file1");

    clo_addOption(list, "tgtfile", CLO_TYPE_IFILE, NULL, "vicarious calibration target file");
    clo_addOption(list, "aerfile", CLO_TYPE_IFILE, NULL, "aerosol model specification file");
    clo_addOption(list, "metafile", CLO_TYPE_IFILE, NULL, "output meta-data file");

    strcpy(tmpStr, "L2 products to be included in ofile #1\n");
    strcat(tmpStr, "   l2prod[#] = L2 products to be included in ofile[#]");
    option = clo_addOption(list, "l2prod", CLO_TYPE_STRING, NULL, tmpStr);
    clo_addOptionAlias(option, "l2prod1");

    clo_addOption(list, "spixl", CLO_TYPE_INT, "1", "start pixel number");
    clo_addOption(list, "epixl", CLO_TYPE_INT, "-1", "end pixel number (-1=the last pixel)");
    clo_addOption(list, "dpixl", CLO_TYPE_INT, "1", "pixel sub-sampling interval");
    clo_addOption(list, "sline", CLO_TYPE_INT, "1", "start line number");
    clo_addOption(list, "eline", CLO_TYPE_INT, "-1", "end line number (-1=the last line)");
    clo_addOption(list, "dline", CLO_TYPE_INT, "1", "line sub-sampling interval");

    strcpy(tmpStr, " control-point pixel increment for lon/lat\n");
    strcat(tmpStr, "        arrays");
    clo_addOption(list, "ctl_pt_incr", CLO_TYPE_INT, "8", tmpStr);

    strcpy(tmpStr, "toggle ocean processing\n");
    strcat(tmpStr, "        1: On\n");
    strcat(tmpStr, "        0: Off\n");
    strcat(tmpStr, "        2: force all pixels to be processed as ocean");
    clo_addOption(list, "proc_ocean", CLO_TYPE_INT, "1", tmpStr);

    clo_addOption(list, "proc_land", CLO_TYPE_BOOL, "off", "toggle land processing");

    strcpy(tmpStr, "toggle SST processing\n");
    strcat(tmpStr, "        (default=1 for MODIS, 0 otherwise)");
    clo_addOption(list, "proc_sst", CLO_TYPE_BOOL, NULL, tmpStr);

    strcpy(tmpStr, "processing mode\n");
    strcat(tmpStr, "        0: forward processing\n");
    strcat(tmpStr, "        1: inverse (calibration) mode, targeting to nLw=0\n");
    strcat(tmpStr, "        2: inverse (calibration) mode, given nLw target\n");
    strcat(tmpStr, "        3: inverse (calibration) mode, given Lw target (internally normalized)");
    clo_addOption(list, "mode", CLO_TYPE_INT, "0", tmpStr);

    strcpy(tmpStr, "seawater IOP options\n");
    strcat(tmpStr, "        0: static values\n");
    strcat(tmpStr, "        1: temperature & salinity-dependent seawater nw, aw, bbw\n");
    clo_addOption(list, "seawater_opt", CLO_TYPE_INT, "0", tmpStr);

    clo_addOption(list, "atmocor", CLO_TYPE_BOOL, "on", "toggle atmospheric correction");

    sprintf(tmpStr, "aerosol mode option\n");
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s      %3d: No aerosol subtraction\n", tmpStr, AERNULL);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s      >0: Multi-scattering with fixed model (provide model number, 1-N,\n", tmpStr1);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s           relative to aermodels list)\n", tmpStr1);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s      %3d: White aerosol extrapolation.\n", tmpStr1, AERWHITE);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s      %3d: Multi-scattering with 2-band model selection\n", tmpStr1, AERWANG);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s      %3d: Multi-scattering with 2-band, RH-based model selection and\n", tmpStr1, AERRHNIR);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s           iterative NIR correction\n", tmpStr1);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s      %3d: Multi-scattering with 2-band model selection\n", tmpStr1, AERWANGNIR);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s           and iterative NIR correction\n", tmpStr1);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s      %3d: Multi-scattering with fixed model pair\n", tmpStr1, FIXMODPAIR);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s           (requires aermodmin, aermodmax, aermodrat specification)\n", tmpStr1);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s      %3d: Multi-scattering with fixed model pair\n", tmpStr1, FIXMODPAIRNIR);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s           and iterative NIR correction\n", tmpStr1);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s           (requires aermodmin, aermodmax, aermodrat specification)\n", tmpStr1);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s      %3d: Multi-scattering with fixed angstrom\n", tmpStr1, FIXANGSTROM);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s           (requires aer_angstrom specification)\n", tmpStr1);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s      %3d: Multi-scattering with fixed angstrom\n", tmpStr1, FIXANGSTROMNIR);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s           and iterative NIR correction\n", tmpStr1);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s           (requires aer_angstrom specification)\n", tmpStr1);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s      %3d: Multi-scattering with fixed aerosol optical thickness\n", tmpStr1, FIXAOT);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s           (requires taua specification)\n", tmpStr1);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s      %3d: Multi-scattering with 2-band model selection using Wang et al. 2009\n", tmpStr1, AERWANGSWIR);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s           to switch between SWIR and NIR. (MODIS only, requires aer_swir_short,\n", tmpStr1);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s           aer_swir_long, aer_wave_short, aer_wave_long)\n", tmpStr1);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s      %3d: Multi-scattering with MUMM correction\n", tmpStr1, AERMUMM);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s           and MUMM NIR calculation \n", tmpStr1);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s      %3d: Spectral optimization via Kuchinke (SeaWiFS-only)\n", tmpStr1, AERSOA);
    strncpy(tmpStr1, tmpStr, 2048);
    sprintf(tmpStr, "%s      %3d: Spectral matching via Gordon (SeaWiFS-only)", tmpStr1, AERSMA);
    clo_addOption(list, "aer_opt", CLO_TYPE_INT, "99", tmpStr);

    clo_addOption(list, "aer_wave_short", CLO_TYPE_INT, "765", "shortest sensor wavelength for aerosol\n        model selection");
    clo_addOption(list, "aer_wave_long", CLO_TYPE_INT, "865", "longest sensor wavelength for aerosol\n        model selection");
    clo_addOption(list, "aer_swir_short", CLO_TYPE_INT, "-1", "shortest sensor wavelength for\n        SWIR-based NIR Lw correction");
    clo_addOption(list, "aer_swir_long", CLO_TYPE_INT, "-1", "longest sensor wavelength for SWIR-based\n        NIR Lw correction");
    clo_addOption(list, "aer_rrs_short", CLO_TYPE_FLOAT, "-1.0", "Rrs at shortest sensor wavelength for\n        aerosol model selection");
    clo_addOption(list, "aer_rrs_long", CLO_TYPE_FLOAT, "-1.0", "Rrs at longest sensor wavelength for\n        aerosol model selection");
    clo_addOption(list, "aermodmin", CLO_TYPE_INT, "-1", "lower-bounding model to use for fixed model\n        pair aerosol option");
    clo_addOption(list, "aermodmax", CLO_TYPE_INT, "-1", "upper-bounding model to use for fixed model\n        pair aerosol option");
    clo_addOption(list, "aermodrat", CLO_TYPE_FLOAT, "0.0", "ratio to use for fixed model pair aerosol\n        option");
    clo_addOption(list, "aer_angstrom", CLO_TYPE_FLOAT, "-999.0", "aerosol angstrom exponent for model\n        selection");
    clo_addOption(list, "aer_iter_max", CLO_TYPE_INT, "10", "maximum number of iterations for NIR\n        water-leaving radiance estimation.");
    clo_addOption(list, "mumm_alpha", CLO_TYPE_FLOAT, "1.72", "water-leaving reflectance ratio for MUMM\n       turbid water atmospheric correction");
    clo_addOption(list, "mumm_gamma", CLO_TYPE_FLOAT, "1.0", "two-way Rayleigh-aerosol transmittance\n       ratio for MUMM turbid water atmospheric correction");
    clo_addOption(list, "mumm_epsilon", CLO_TYPE_FLOAT, "1.0", "aerosol reflectance ratio for MUMM\n        turbid water atmospheric correction");
    clo_addOption(list, "degc", CLO_TYPE_INT, "0", "Deg C for AVHRR");

    strcpy(tmpStr, "absorbing aerosol flagging option\n");
    strcat(tmpStr, "       -1: disable\n");
    strcat(tmpStr, "        0: use rhow constant\n");
    strcat(tmpStr, "        1: apply chlorophyll climatology to calculate rhow\n");
    strcat(tmpStr, "        2: 1+validate against nLw_412 climatology");
    clo_addOption(list, "absaer_opt", CLO_TYPE_INT, "-1", tmpStr);

    strcpy(tmpStr, "glint correction:\n");
    strcat(tmpStr, "        0: glint correction off\n");
    strcat(tmpStr, "        1: standard glint correction\n");
    strcat(tmpStr, "        2: simple glint correction");
    clo_addOption(list, "glint_opt", CLO_TYPE_INT, "1", tmpStr);

    strcpy(tmpStr, "out-of-band correction for water-leaving\n");
    strcat(tmpStr, "        radiances\n");
    strcat(tmpStr, "        2: On (default for MODIS, SeaWiFS, OCTS)\n");
    strcat(tmpStr, "        0: Off (default for MOS, OSMI)");
    clo_addOption(list, "outband_opt", CLO_TYPE_INT, "99", tmpStr);

    clo_addOption(list, "oxaband_opt", CLO_TYPE_BOOL, NULL, "oxygen a-band correction option\n        (default On for SeaWiFS, OSMI, and OCTS, Off otherwise)");
    clo_addOption(list, "filter_opt", CLO_TYPE_BOOL, NULL, "filtering input data option\n        (default On for OCTS, Off otherwise)");
    clo_addOption(list, "filter_file", CLO_TYPE_IFILE, "$OCDATAROOT/sensor/sensor_filter.dat", "\n        data file for input filtering");

    strcpy(tmpStr, "Bidirectional reflectance correction\n");
    strcat(tmpStr, "        0: no correction\n");
    strcat(tmpStr, "        1: Fresnel reflection/refraction correction for sensor path\n");
    strcat(tmpStr, "        3: Fresnel reflection/refraction correction for sensor + solar path\n");
    strcat(tmpStr, "        7: Morel f/Q + Fresnel solar + Fresnel sensor\n");
    strcat(tmpStr, "       15: Gordon DT + Morel f/Q + Fresnel solar + Fresnel sensor\n");
    strcat(tmpStr, "       19: Morel Q + Fresnel solar + Fresnel sensor");
    clo_addOption(list, "brdf_opt", CLO_TYPE_INT, "-1", tmpStr);

    strcpy(tmpStr, "gaseous transmittance bitmask selector\n");
    strcat(tmpStr, "        0: no correction\n");
    strcat(tmpStr, "        1: Ozone\n");
    strcat(tmpStr, "        2: CO2\n");
    strcat(tmpStr, "        4: NO2\n");
    strcat(tmpStr, "        8: H2O");
    clo_addOption(list, "gas_opt", CLO_TYPE_INT, "1", tmpStr);

    strcpy(tmpStr, "IOP model for use in downstream products\n");
    strcat(tmpStr, "        0: None (products requiring a or bb will fail)\n");
    strcat(tmpStr, "        1: Carder\n");
    strcat(tmpStr, "        2: GSM\n");
    strcat(tmpStr, "        3: QAA\n");
    strcat(tmpStr, "        4: PML\n");
    strcat(tmpStr, "        5: NIWA\n");
    strcat(tmpStr, "        6: LAS\n");
    strcat(tmpStr, "        7: GIOP");
    clo_addOption(list, "iop_opt", CLO_TYPE_INT, "0", tmpStr);

    clo_addOption(list, "polfile", CLO_TYPE_IFILE, NULL, "polarization sensitivities filename leader");

    strcpy(tmpStr, "polarization correction (sensor-specific)\n");
    strcat(tmpStr, "        0: no correction\n");
    strcat(tmpStr, "        1: only Rayleigh component is polarized\n");
    strcat(tmpStr, "        2: all radiance polarized like Rayleigh\n");
    strcat(tmpStr, "        3: only Rayleigh and Glint are polarized (MODIS default)\n");
    strcat(tmpStr, "        4: all radiance polarized like Rayleigh + Glint");
    clo_addOption(list, "pol_opt", CLO_TYPE_INT, "-1", tmpStr);

    strcpy(tmpStr, "radiation correction option (sensor-specific)\n");
    strcat(tmpStr, "        0: no correction\n");
    strcat(tmpStr, "        1: apply MERIS Smile correction");
    clo_addOption(list, "rad_opt", CLO_TYPE_INT, "0", tmpStr);

    strcpy(tmpStr, "switch to ocean color virtual constellation\n");
    strcat(tmpStr, "        0: no\n");
    strcat(tmpStr, "        1: yes");
    clo_addOption(list, "ocrvc_opt", CLO_TYPE_INT, "0", tmpStr);

    clo_addOption(list, "xcalfile", CLO_TYPE_IFILE, NULL, "cross-calibration file");

    strcpy(tmpStr, "cross-calibration option (sensor-specific) comma separated\n");
    strcat(tmpStr, "        list of option values, 1 per band, with bands listed in xcal_wave.\n");
    strcat(tmpStr, "        3: apply cross-calibration corrections (polarization and rvs)\n");
    strcat(tmpStr, "        2: apply cross-calibration polarization corrections\n");
    strcat(tmpStr, "        1: apply cross-calibration rvs corrections\n");
    strcat(tmpStr, "        0: no correction");
    clo_addOption(list, "xcal_opt", CLO_TYPE_INT, NULL, tmpStr);

    strcpy(tmpStr, "wavelengths at which to apply cross-calibration.  Comma\n");
    strcat(tmpStr, "        separated list of sensor wavelength values associated with xcal_opt.");
    clo_addOption(list, "xcal_wave", CLO_TYPE_FLOAT, NULL, tmpStr);

    strcpy(tmpStr, "processing resolution (MODIS only)\n");
    strcat(tmpStr, "       -1: standard ocean 1km processing\n");
    strcat(tmpStr, "     1000: 1km resolution including aggregated 250 and 500m land bands\n");
    strcat(tmpStr, "      500: 500m resolution including aggregated 250 land bands and\n");
    strcat(tmpStr, "           replication for lower resolution bands\n");
    strcat(tmpStr, "      250: 250m resolution with replication for lower resolution bands");
    clo_addOption(list, "resolution", CLO_TYPE_INT, "-1", tmpStr);

    strcpy(tmpStr, "GIOP model aph function type\n");
    strcat(tmpStr, "        0: tabulated (supplied via giop_aph_file)\n");
    strcat(tmpStr, "        2: Bricaud et al. 1995 (chlorophyll supplied via default empirical algorithm)\n");
    strcat(tmpStr, "        3: Ciotti and Bricaud 2006 (size fraction supplied via giop_aph_s)");
    clo_addOption(list, "giop_aph_opt", CLO_TYPE_INT, "2", tmpStr);
    clo_addOption(list, "giop_aph_file", CLO_TYPE_IFILE, "$OCDATAROOT/common/aph_default.txt", "\n        GIOP model, tabulated aph spectra");
    clo_addOption(list, "giop_aph_s", CLO_TYPE_FLOAT, "-1000.0", "GIOP model, spectral parameter\n        for aph");

    strcpy(tmpStr, "GIOP model adg function type\n");
    strcat(tmpStr, "        0: tabulated (supplied via giop_adg_file)\n");
    strcat(tmpStr, "        1: exponential with exponent supplied via giop_adg_s)\n");
    strcat(tmpStr, "        2: exponential with exponent derived via Lee et al. (2002)\n");
    strcat(tmpStr, "        3: exponential with exponent derived via OBPG method");
    clo_addOption(list, "giop_adg_opt", CLO_TYPE_INT, "1", tmpStr);
    clo_addOption(list, "giop_adg_file", CLO_TYPE_STRING, "$OCDATAROOT/common/adg_default.txt", "\n        GIOP model, tabulated adg spectra");
    clo_addOption(list, "giop_adg_s", CLO_TYPE_FLOAT, "0.0145", "GIOP model, spectral parameter\n        for adg");

    strcpy(tmpStr, "GIOP model bbp function type\n");
    strcat(tmpStr, "        0: tabulated (supplied via giop_bbp_file)\n");
    strcat(tmpStr, "        1: power-law with exponent supplied via giop_bbp_s)\n");
    strcat(tmpStr, "        2: power-law with exponent derived via Hoge & Lyon (1996)\n");
    strcat(tmpStr, "        3: power-law with exponent derived via Lee et al. (2002)\n");
    strcat(tmpStr, "        5: power-law with exponent derived via Ciotti et al. (1999)\n");
    strcat(tmpStr, "        6: power-law with exponent derived via Morel & Maritorena (2001)\n");
    strcat(tmpStr, "        7: power-law with exponent derived via Loisel & Stramski (2000)\n");
    strcat(tmpStr, "        8: spectrally independent vector derived via Loisel & Stramski (2000)\n");
    strcat(tmpStr, "        9: fixed vector derived via Loisel & Stramski (2000)\n");
    strcat(tmpStr, "       10: fixed vector derived via lee et al. (2002)");
    clo_addOption(list, "giop_bbp_opt", CLO_TYPE_INT, "3", tmpStr);
    clo_addOption(list, "giop_bbp_file", CLO_TYPE_IFILE, "$OCDATAROOT/common/bbp_default.txt", "\n        GIOP model, tabulated bbp spectra");
    clo_addOption(list, "giop_bbp_s", CLO_TYPE_FLOAT, "-1000.0", "GIOP model, spectral parameter\n        for bbp");

    strcpy(tmpStr, "GIOP model Rrs to bb/(a+bb) method\n");
    strcat(tmpStr, "        0: Gordon quadratic (specified with giop_grd)\n");
    strcat(tmpStr, "        1: Morel f/Q");
    clo_addOption(list, "giop_rrs_opt", CLO_TYPE_INT, "1", tmpStr);
    clo_addOption(list, "giop_grd", CLO_TYPE_FLOAT, "[0.0949,0.0794]", "GIOP model, Gordon\n        Rrs to bb/(a+bb) quadratic coefficients");

    strcpy(tmpStr, "GIOP model list of sensor wavelengths for\n");
    strcat(tmpStr, "        optimization comma-separated list, default is all visible bands (400-700nm)");
    clo_addOption(list, "giop_wave", CLO_TYPE_FLOAT, "-1", tmpStr);
    clo_addOption(list, "giop_rrs_unc", CLO_TYPE_FLOAT, "-1", tmpStr);
    clo_addOption(list, "giop_maxiter", CLO_TYPE_INT, "50", "GIOP Model iteration limit");

    strcpy(tmpStr, "GIOP model optimization method\n");
    strcat(tmpStr, "        0: Amoeba optimization\n");
    strcat(tmpStr, "        1: Levenberg-Marquardt optimization\n");
    strcat(tmpStr, "        3: SVD matrix inversion");
    clo_addOption(list, "giop_fit_opt", CLO_TYPE_INT, "1", tmpStr);

    strcpy(tmpStr, "GIOP temperature and salinity dependence\n");
    strcat(tmpStr, "        0: none\n");
    strcat(tmpStr, "        1: apply to bbw\n");
    clo_addOption(list, "giop_ts_opt", CLO_TYPE_INT, "0", tmpStr);

    strcpy(tmpStr, "GSM model options\n");
    strcat(tmpStr, "        0: default coefficients\n");
    strcat(tmpStr, "        1: Chesapeake regional coefficients");
    clo_addOption(list, "gsm_opt", CLO_TYPE_INT, "0", tmpStr);

    strcpy(tmpStr, "SM fit algorithm\n");
    strcat(tmpStr, "        0: Amoeba\n");
    strcat(tmpStr, "        1: Levenberg-Marquardt");
    clo_addOption(list, "gsm_fit", CLO_TYPE_INT, "0", tmpStr);

    clo_addOption(list, "gsm_adg_s", CLO_TYPE_FLOAT, "0.02061", "GSM IOP model, spectral slope for adg");
    clo_addOption(list, "gsm_bbp_s", CLO_TYPE_FLOAT, "1.03373", "GSM IOP model, spectral slope for bbp");
    clo_addOption(list, "gsm_aphw", CLO_TYPE_FLOAT, "[412.0, 443.0, 490.0, 510.0, 555.0, 670.0]", "\n        GSM IOP model, wavelengths of ap* table");
    clo_addOption(list, "gsm_aphs", CLO_TYPE_FLOAT, "[0.00665, 0.05582, 0.02055, 0.01910, 0.01015, 0.01424]", "GSM IOP model, coefficients of ap* table");

    option = clo_addOption(list, "qaa_adg_s", CLO_TYPE_FLOAT, "0.015", "QAA IOP model, spectral\n        slope for adg");
    clo_addOptionAlias(option, "qaa_S");

    clo_addOption(list, "qaa_wave", CLO_TYPE_INT, NULL, "sensor wavelengths for QAA algorithm");
    clo_addOption(list, "chloc2_wave", CLO_TYPE_INT, "[-1,-1]", "sensor wavelengths for OC2 chlorophyll\n        algorithm");
    clo_addOption(list, "chloc2_coef", CLO_TYPE_FLOAT, "[0.0,0.0,0.0,0.0,0.0]", "coefficients for OC2\n        chlorophyll algorithm");
    clo_addOption(list, "chloc3_wave", CLO_TYPE_INT, "[-1,-1,-1]", "sensor wavelengths for OC3\n         chlorophyll algorithm");
    clo_addOption(list, "chloc3_coef", CLO_TYPE_FLOAT, "[0.0,0.0,0.0,0.0,0.0]", "coefficients for OC3\n        chlorophyll algorithm");
    clo_addOption(list, "chloc4_wave", CLO_TYPE_INT, "[-1,-1,-1,-1]", "sensor wavelengths for OC4\n        chlorophyll algorithm");
    clo_addOption(list, "chloc4_coef", CLO_TYPE_FLOAT, "[0.0,0.0,0.0,0.0,0.0]", "coefficients for OC4\n        chlorophyll algorithm");
    clo_addOption(list, "chlclark_wave", CLO_TYPE_INT, "[-1,-1,-1]", "sensor wavelengths for Clark\n        chlorophyll algorithm");
    clo_addOption(list, "chlclark_coef", CLO_TYPE_FLOAT, "[0.0,0.0,0.0,0.0,0.0,0.0]", "coefficients for\n        Clark chlorophyll algorithm");
    clo_addOption(list, "kd2_wave", CLO_TYPE_INT, "[-1,-1]", "sensor wavelengths for polynomial Kd(490)\n        algorithm");
    clo_addOption(list, "kd2_coef", CLO_TYPE_FLOAT, "[0.0,0.0,0.0,0.0,0.0,0.0]", "sensor wavelengths\n        for polynomial Kd(490) algorithm");
    clo_addOption(list, "flh_offset", CLO_TYPE_FLOAT, "0.0", "bias to subtract\n        from retrieved fluorescence line height");
    clo_addOption(list, "btfile", CLO_TYPE_IFILE, NULL, "IR brightness temperature file");
    clo_addOption(list, "sstcoeffile", CLO_TYPE_IFILE, NULL, "IR sst algorithm coefficients file");
    clo_addOption(list, "sstssesfile", CLO_TYPE_IFILE, NULL, "IR sst algorithm error statistics file");
    clo_addOption(list, "sstmirrfile", CLO_TYPE_IFILE, NULL, "IR sst algorithm mirror-side corrections file");
    clo_addOption(list, "sst4coeffile", CLO_TYPE_IFILE, NULL, "SWIR sst algorithm coefficients file");
    clo_addOption(list, "sst4ssesfile", CLO_TYPE_IFILE, NULL, "SWIR sst algorithm error statistics file");
    clo_addOption(list, "sst4mirrfile", CLO_TYPE_IFILE, NULL, "SWIR sst algorithm mirror-side corrections file");
    clo_addOption(list, "vcnnfile", CLO_TYPE_IFILE, NULL, "virtual constellation neural net file");
    clo_addOption(list, "owtfile", CLO_TYPE_IFILE, NULL, "optical water type file");
    clo_addOption(list, "owtchlerrfile", CLO_TYPE_IFILE, NULL, "chl error file associate with optical water type");

    strcpy(tmpStr, "[");
    strcat(tmpStr, defaermodels[0]);
    for (i = 1; i < defnaermodels; i++) {
        strcat(tmpStr, ",");
        strcat(tmpStr, defaermodels[i]);
    }
    strcat(tmpStr, "]");
    clo_addOption(list, "aermodels", CLO_TYPE_STRING, tmpStr, "aerosol models");

    clo_addOption(list, "met1", CLO_TYPE_IFILE, "$OCDATAROOT/common/met_climatology.hdf", "\n        1st meteorological ancillary data file");
    clo_addOption(list, "met2", CLO_TYPE_IFILE, NULL, "2nd meteorological ancillary data file");
    clo_addOption(list, "met3", CLO_TYPE_IFILE, NULL, "3rd meteorological ancillary data file");
    clo_addOption(list, "ozone1", CLO_TYPE_IFILE, "$OCDATAROOT/common/ozone_climatology.hdf", "\n        1st ozone ancillary data file");
    clo_addOption(list, "ozone2", CLO_TYPE_IFILE, NULL, "2nd ozone ancillary data file");
    clo_addOption(list, "ozone3", CLO_TYPE_IFILE, NULL, "3rd ozone ancillary data file");
    clo_addOption(list, "land", CLO_TYPE_IFILE, "$OCDATAROOT/common/landmask.dat", "land mask file");
    clo_addOption(list, "water", CLO_TYPE_IFILE, "$OCDATAROOT/common/watermask.dat", "\n        shallow water mask file");
    clo_addOption(list, "demfile", CLO_TYPE_IFILE, "$OCDATAROOT/common/digital_elevation_map.hdf", "\n        digital elevation map file");
    clo_addOption(list, "icefile", CLO_TYPE_IFILE, "$OCDATAROOT/common/ice_mask.hdf", "sea ice file");
    clo_addOption(list, "ice_threshold", CLO_TYPE_FLOAT, "0.1", "sea ice fraction above which will be\n        flagged as sea ice");
    clo_addOption(list, "sstfile", CLO_TYPE_IFILE, "$OCDATAROOT/common/sst_climatology.hdf", "input\n        SST reference file");
    clo_addOption(list, "sssfile", CLO_TYPE_IFILE, "$OCDATAROOT/common/sss_climatology_woa2009.hdf", "input\n        SSS reference file");
    clo_addOption(list, "no2file", CLO_TYPE_IFILE, "$OCDATAROOT/common/no2_climatology.hdf", "no2\n        ancillary file");
    clo_addOption(list, "alphafile", CLO_TYPE_IFILE, "$OCDATAROOT/common/alpha510_climatology.hdf", "\n        alpha510 climatology file");
    clo_addOption(list, "tauafile", CLO_TYPE_IFILE, "$OCDATAROOT/common/taua865_climatology.hdf", "\n        taua865 climatology file");
    clo_addOption(list, "cldfile", CLO_TYPE_IFILE, NULL, "cloud mask file (MODIS only)");
    clo_addOption(list, "calfile", CLO_TYPE_IFILE, NULL, "system calibration file");
    clo_addOption(list, "offset", CLO_TYPE_FLOAT, NULL, "calibration offset adjustment");
    clo_addOption(list, "gain", CLO_TYPE_FLOAT, NULL, "calibration gain multiplier");
    clo_addOption(list, "gain_unc", CLO_TYPE_FLOAT, NULL, "calibration gain uncertainty");
    clo_addOption(list, "flaguse", CLO_TYPE_STRING, default_flaguse, "Flags to use");
    clo_addOption(list, "xcalbox", CLO_TYPE_INT, "0", "pixel size of the central box in the L1 scene\n        (e.g. 5 pixels around MOBY) to be extracted into xcalfile for the\n        cross-calibration, 0=whole L1");
    clo_addOption(list, "xcalboxcenter", CLO_TYPE_INT, "[0,0]", "Central [ipix, iscan] of the box in\n        the L1 scene, [0,0] = center of the L1 scene");
    clo_addOption(list, "xcalpervalid", CLO_TYPE_INT, "0", "min percent of valid cross-calibration\n        pixels within the box or the L1 scene, 0 = at least 1 pixel");
    clo_addOption(list, "xcalsubsmpl", CLO_TYPE_INT, "1", "Sub-sampling rate for the data to be used\n        for the cross-calibration");

    strcpy(tmpStr, "use deep water mask to select data for\n");
    strcat(tmpStr, "        target file:\n");
    strcat(tmpStr, "        0: no selection with mask\n");
    strcat(tmpStr, "        1: use deep water mask");
    clo_addOption(list, "vct_msk_water", CLO_TYPE_INT, "1", tmpStr);

    strcpy(tmpStr, "\n        name of deep water mask to use");
    clo_addOption(list, "vct_water", CLO_TYPE_IFILE,
            "$OCDATAROOT/common/deep_water_mask_9km.dat", tmpStr);

    strcpy(tmpStr, "minimum # of samples in a bin for acceptance");
    clo_addOption(list, "vct_min_nbin", CLO_TYPE_INT, "4", tmpStr);

    strcpy(tmpStr, "minimum % of samples filled in target\n        file to allow target file creation, if greater than 0,\n        create target, aerosol files regardless");
    clo_addOption(list, "vct_fill_pct", CLO_TYPE_FLOAT, "0.04", tmpStr);

    strcpy(tmpStr, "max distance between L1 and L2 pixels\n");
    strcat(tmpStr, "       in km\n");
    strcat(tmpStr, "       -1.0: use mean res of L1 data\n");
    strcat(tmpStr, "        0.0: max{mean(L1 res),mean(L2 res)}");
    clo_addOption(list, "maxpointdist", CLO_TYPE_FLOAT, "0.0", tmpStr);

    sprintf(tmpStr2, "%f", CHL_MAX);
    sprintf(tmpStr, "threshold on L2 data chlorophyll\n        (%f=CHL_MAX)",
            CHL_MAX);
    clo_addOption(list, "chlthreshold", CLO_TYPE_FLOAT, tmpStr2, tmpStr);

    sprintf(tmpStr2, "%f", AOT_MAX);
    sprintf(tmpStr, "threshold on L2 data AOTs\n        (%f=AOT_MAX)", AOT_MAX);
    clo_addOption(list, "aotthreshold", CLO_TYPE_FLOAT, tmpStr2, tmpStr);

    strcpy(tmpStr, "\n        coccolithophore algorithm coefs");
    clo_addOption(list, "coccolith", CLO_TYPE_FLOAT, "[1.1,0.9,0.75,1.85,1.0,1.65,0.6,1.15]", tmpStr);

    clo_addOption(list, "cirrus_thresh", CLO_TYPE_FLOAT, "[-1.0,-1.0]", "cirrus reflectance thresholds");
    clo_addOption(list, "taua", CLO_TYPE_FLOAT, NULL, "[taua_band1,...,taua_bandn] aerosol optical thickness of the\n        calibration data point");
    option = clo_addOption(list, "cloud_thresh", CLO_TYPE_FLOAT, "0.027", "cloud reflectance\n        threshold");
    clo_addOptionAlias(option, "albedo");
    clo_addOption(list, "cloud_wave", CLO_TYPE_FLOAT, "865.0", "wavelength of cloud reflectance test");
    clo_addOption(list, "cloud_eps", CLO_TYPE_FLOAT, "-1.0", "cloud reflectance ratio threshold\n        (-1.0=disabled)");
    option = clo_addOption(list, "glint_thresh", CLO_TYPE_FLOAT, "0.005", "high sun glint threshold");
    clo_addOptionAlias(option, "glint");
    clo_addOption(list, "absaer", CLO_TYPE_FLOAT, "0.0", "absorbing aerosol threshold on aerosol index");
    clo_addOption(list, "rhoamin", CLO_TYPE_FLOAT, "0.0001", "min NIR aerosol reflectance to attempt\n        model lookup");
    clo_addOption(list, "sunzen", CLO_TYPE_FLOAT, "75.0", "sun zenith angle threshold in deg.");
    clo_addOption(list, "satzen", CLO_TYPE_FLOAT, "60.0", "satellite zenith angle threshold");
    clo_addOption(list, "epsmin", CLO_TYPE_FLOAT, "0.85", "minimum epsilon to trigger atmospheric\n        correction failure flag");
    clo_addOption(list, "epsmax", CLO_TYPE_FLOAT, "1.35", "maximum epsilon to trigger atmospheric\n         correction failure flag");
    clo_addOption(list, "tauamax", CLO_TYPE_FLOAT, "0.3", "maximum 865 aerosol optical depth to trigger\n        hitau flag");
    clo_addOption(list, "nLwmin", CLO_TYPE_FLOAT, "0.15", "minimum nLw(555) to trigger low Lw flag");
    clo_addOption(list, "hipol", CLO_TYPE_FLOAT, "0.5", "threshold on degree-of-polarization to set\n        HIPOL flag");
    clo_addOption(list, "wsmax", CLO_TYPE_FLOAT, "8.0", "windspeed limit on white-cap correction in m/s");
    clo_addOption(list, "windspeed", CLO_TYPE_FLOAT, "-1000.0", "user over-ride of windspeed in m/s\n        (-1000=use ancillary files)");
    clo_addOption(list, "windangle", CLO_TYPE_FLOAT, "-1000.0", "user over-ride of wind angle in deg\n        (-1000=use ancillary files)");
    clo_addOption(list, "pressure", CLO_TYPE_FLOAT, "-1000.0", "user over-ride of atmospheric pressure\n        in mb (-1000=use ancillary files)");
    clo_addOption(list, "ozone", CLO_TYPE_FLOAT, "-1000.0", "user over-ride of ozone concentration in\n        cm (-1000=use ancillary files)");
    clo_addOption(list, "relhumid", CLO_TYPE_FLOAT, "-1000.0", "user over-ride of relative humidity in\n        percent (-1000=use ancillary files)");
    clo_addOption(list, "watervapor", CLO_TYPE_FLOAT, "-1000.0", "user over-ride of water vapor in\n        g/cm^2 (-1000=use ancillary files)");
    clo_addOption(list, "maskland", CLO_TYPE_BOOL, "on", "land mask option");
    clo_addOption(list, "maskbath", CLO_TYPE_BOOL, "off", "shallow water mask option");
    clo_addOption(list, "maskcloud", CLO_TYPE_BOOL, "on", "cloud mask option");
    clo_addOption(list, "maskglint", CLO_TYPE_BOOL, "off", "glint mask option");
    clo_addOption(list, "masksunzen", CLO_TYPE_BOOL, "off", "large sun zenith angle mask option");
    clo_addOption(list, "masksatzen", CLO_TYPE_BOOL, "off", "large satellite zenith angle mask option");
    clo_addOption(list, "maskhilt", CLO_TYPE_BOOL, "on", "high Lt masking");
    clo_addOption(list, "maskstlight", CLO_TYPE_BOOL, "on", "stray light masking");
    clo_addOption(list, "sl_frac", CLO_TYPE_FLOAT, "0.25", "SeaWiFS only, straylight fractional\n        threshold on Ltypical");
    clo_addOption(list, "sl_pixl", CLO_TYPE_INT, "-1", "SeaWiFS only, number of LAC pixels for\n        straylight flagging");
    clo_addOption(list, "vcal_opt", CLO_TYPE_INT, "-1", "Vicarious calibration option");
    clo_addOption(list, "vcal_chl", CLO_TYPE_FLOAT, "-1.0", "Vicarious calibration chl");
    clo_addOption(list, "vcal_solz", CLO_TYPE_FLOAT, "-1.0", "Vicarious calibration solz");
    clo_addOption(list, "vcal_nLw", CLO_TYPE_FLOAT, NULL, "Vicarious calibration normalized water leaving radiances");
    clo_addOption(list, "vcal_Lw", CLO_TYPE_FLOAT, NULL, "Vicarious calibration water leaving radiances");
    clo_addOption(list, "owmcfile", CLO_TYPE_IFILE, "$OCDATAROOT/common/owmc_lut.hdf", "lut for OWMC\n        classification");

    clo_addOption(list, "stype", CLO_TYPE_INT, "0", "scaling type\n        0: log\n        1: linear");
    clo_addOption(list, "rgb", CLO_TYPE_INT, "[1,1,1]", "bands to use for red, green and blue");
    clo_addOption(list, "north", CLO_TYPE_FLOAT, "-999", "north boundary");
    clo_addOption(list, "south", CLO_TYPE_FLOAT, "-999", "south boundary");
    clo_addOption(list, "east", CLO_TYPE_FLOAT, "-999", "east boundary");
    clo_addOption(list, "west", CLO_TYPE_FLOAT, "-999", "west boundary");
    clo_addOption(list, "xbox", CLO_TYPE_INT, "-1", "number of pixels on either side of the SW point");
    clo_addOption(list, "ybox", CLO_TYPE_INT, "-1", "number of scan lines on either side of the SW point");

    clo_addOption(list, "width", CLO_TYPE_INT, "600", "width of output image");
    clo_addOption(list, "threshold", CLO_TYPE_FLOAT, "0.1", "threshold for the number of good pixels\n        before an image is produced");
    clo_addOption(list, "datamin", CLO_TYPE_FLOAT, "0.01", "minimum reflectance for scaling");
    clo_addOption(list, "datamax", CLO_TYPE_FLOAT, "0.9", "maximum reflectance for scaling");
    clo_addOption(list, "subsamp", CLO_TYPE_INT, "1", "sub-sampling interval");

    if (!strcmp(prog, "l1mapgen")) {
        strcpy(tmpStr, "defines output format\n");
        strcat(tmpStr, "        ppm: PPM file (alias 0)\n");
        strcat(tmpStr, "        png: PNG file (alias 1)\n");
        strcat(tmpStr, "        tiff: GeoTIFF (alias 2)");
        clo_addOption(list, "outmode", CLO_TYPE_STRING, "ppm", tmpStr);
    } else {
        strcpy(tmpStr, "defines output format\n");
        strcat(tmpStr, "        8bit: 8bit HDF (alias 0)\n");
        strcat(tmpStr, "        24bit: 24bit HDF (alias 1)\n");
        strcat(tmpStr, "        ppm: PPM file (alias 2)\n");
        strcat(tmpStr, "        bin: flat binary (alias 3)\n");
        strcat(tmpStr, "        png: PNG file (alias 4)");
        clo_addOption(list, "outmode", CLO_TYPE_STRING, "8bit", tmpStr);
    }

    clo_addOption(list, "prodxmlfile", CLO_TYPE_OFILE, NULL, "output XML file describing all possible products");

    strcpy(tmpStr, "\nThis program produces a PPM-formatted output image rendered in a Plate Carree\n");
    strcat(tmpStr, "projection.\n\n");
    strcat(tmpStr, "The default band combination produces a \"true-color\" image. Other combinations\n");
    strcat(tmpStr, "may be chosen with the \"rgb=\" option.  The expected argument to this option is\n");
    strcat(tmpStr, "a comma separated string of wavelengths that specifies the desired bands in\n");
    strcat(tmpStr, "red-green-blue order.  For example, to produce a false color SeaWiFS output\n");
    strcat(tmpStr, "image using 865, 670 and 555 nm as the red, green, and blue values\n");
    strcat(tmpStr, "respectively, the option would be specified as \"rgb=865,670,555\".\n");
    clo_addOption(list, "help_true_color", CLO_TYPE_HELP, "0", tmpStr);

    return 0;
}

//-----------------------------------------------------------------------

/* 
   Read the command line option and all of the default parameter files.

   This is the order for loading the options:
    - read the command line to get the ifile and suite options
    - load the main program defaults file
    - load the sensor specific defaults file
    - load the sub-sensor defaults file
    - load the suite file
    - load the command line (including specified par files)
    - re-load the command line so they take precedence

 */
extern char * rootdatapath;

int l2gen_read_options(clo_optionList_t* list, char* progName,
        int argc, char* argv[], filehandle *l1file) {
    char *dataRoot;
    char tmpStr[FILENAME_MAX];
    char *ifile;
    clo_option_t* option;
    char localSuite[FILENAME_MAX];
    int i;
    char l2genProgName[] = "msl12";

    assert(list);

    dataRoot = g_cfg.config_f;

    // disable the dump option until we have read all of the files
    clo_setEnableDumpOptions(0);

    //    // read command line args to get the ifile parameter
    //    enableFileDecending = 1;
    //    clo_readArgs(list, argc, argv);
    //    // if a file was decended, make sure the command args over-rides
    //    enableFileDecending = 0;
    //    clo_readArgs(list, argc, argv);
    //    enableFileDecending = 1;

    //    // see if suite param was set
    //    localSuite[0] = '\0';
    //    if (clo_isSet(list, "suite")) {
    //        strcpy(localSuite, clo_getString(list, "suite"));
    //    } // suite option was set

    //    ifile = clo_getString(list, "ifile");
    //    i = clo_getInt(list, "resolution");
//  //      i=-1000;
    //    if (i == -1000)
    //        l1file->modis_subset_compat = 1;
    //    i = clo_getInt(list, "ocrvc_opt");
//  //      i=0;
    //    l1file->ocrvc_opt = i;
    //    strcpy(l1file->name, ifile);

    // load program defaults
    sprintf(tmpStr, "%s/%s_defaults_coeffcalc.par", dataRoot, l2genProgName);
    if (want_verbose)
        HY1C_out("Loading default parameters from %s\n", tmpStr);
    clo_readFile(list, tmpStr);

    //    // if suite not set on command line or param file then use the default
    //    if (localSuite[0] == '\0')
    //        strcpy(localSuite, clo_getString(list, "suite"));

    //    // set the default l2prod lists before the command line or par file
    //    // is loaded
    //    option = clo_findOption(list, "l2prod");
    //    if (option && clo_isOptionSet(option))
    //        strcpy(default_l2prod[0], option->valStr);
    //    for (i = 0; i < MAX_OFILES; i++) {
    //        sprintf(tmpStr, "l2prod%d", i + 1);
    //        option = clo_findOption(list, tmpStr);
    //        if (option && clo_isOptionSet(option))
    //            strcpy(default_l2prod[i], option->valStr);
    //        else
    //            default_l2prod[i][0] = '\0';
    //    }

    //    // re-load the command line and par file
    //    if (want_verbose)
    //        HY1C_out("Loading command line parameters\n\n");
    //    enableFileDecending = 1;
    //    clo_readArgs(list, argc, argv);

    //    // enable the dump option the last time through
    //    clo_setEnableDumpOptions(1);

    //    // disable file decending so the command line options override
    //    // anything that is in a parameter file
    //    enableFileDecending = 0;
    //    clo_readArgs(list, argc, argv);

    return 0;
}

//-----------------------------------------------------------------------------

int l2gen_load_input(clo_optionList_t *list, instr *input) {
    char str_buf[FILENAME_MAX];
    char str_buf2[FILENAME_MAX];
    char tmp_file[FILENAME_MAX];
    char *strVal;
    clo_option_t *option;
    int numOptions;
    int optionId;
    char keyword[FILENAME_MAX];
    int count;
    char **strArray;
    float *fArray;
    int *iArray;
    int i, j;
    FILE *fp;


    // first load up the default_l2prod
    for (i = 0; i < MAX_OFILES; i++) {
        if (default_l2prod[i][0]) {
            strcpy(input->def_l2prod[i], default_l2prod[i]);
        }
    }

    numOptions = clo_getNumOptions(list);
    for (optionId = 0; optionId < numOptions; optionId++) {
        option = clo_getOption(list, optionId);

        // ignore options of type CLO_TYPE_HELP 
        if(option->dataType == CLO_TYPE_HELP)
            continue;
        
        strcpy(keyword, option->key);

        /* change keyword to lower case */
        strVal = keyword;
        while (*strVal != '\0') {
            *strVal = tolower(*strVal);
            strVal++;
        }

        if (strcmp(keyword, "-help") == 0)
            ;
        else if (strcmp(keyword, "-version") == 0)
            ;
        else if (strncmp(keyword, "-dump_options", 13) == 0)
            ;
        else if (strcmp(keyword, "par") == 0)
            ;
        else if (strcmp(keyword, "ifile") == 0) {
            strVal = clo_getOptionString(option);
            parse_file_name(strVal, tmp_file);
            strcpy(input->ifile[0], tmp_file);

        } else if (strncmp(keyword, "ifile", 5) == 0) {
            for (i = 1; i < MAX_IFILES; i++) {
                sprintf(str_buf, "ifile%d", i + 1);
                if (strcmp(keyword, str_buf) == 0) {
                    if (i == 0)
                        break;
                    strVal = clo_getOptionString(option);
                    parse_file_name(strVal, tmp_file);
                    strcpy(input->ifile[i], tmp_file);
                    break;
                }
            }
            if (i >= MAX_IFILES) {
                HY1C_out("-E- l2gen_load_input: %s bigger than MAX_IFILES(%d)\n",
                        keyword, MAX_IFILES);
                return -1;
            }

        } else if (strcmp(keyword, "ilist") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                if ((fp = fopen(tmp_file, "r")) == NULL) {
                    HY1C_out("Error: Unable to open input file list %s\n", tmp_file);
                    return -1;
                }
                tmp_file[0] = '\x0';
                for (i = 0; i < MAX_IFILES; i++) {
                    if (fscanf(fp, "%s\n", tmp_file) != EOF) {
                        strcpy((input->ifile)[i], tmp_file);
                        sprintf(str_buf, "ifile%d", i + 1);
                        sprintf(str_buf2, "ilist=%s", strVal);
                        clo_setString(list, str_buf, tmp_file, str_buf2);
                    } else
                        break;
                }
                fclose(fp);
            }

        } else if (strcmp(keyword, "calfile") == 0) {
            strVal = clo_getOptionString(option);
            parse_file_name(strVal, tmp_file);
            strcpy(input->calfile, tmp_file);

        } else if (strcmp(keyword, "cldfile") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->cldfile, tmp_file);
            }

        } else if (strcmp(keyword, "ofile") == 0) {
            strVal = clo_getOptionString(option);
            parse_file_name(strVal, tmp_file);
            strcpy(input->ofile[0], tmp_file);

        } else if (strncmp(keyword, "ofile", 5) == 0) {
            for (i = 1; i < MAX_OFILES; i++) {
                sprintf(str_buf, "ofile%d", i + 1);
                if (strcmp(keyword, str_buf) == 0) {
                    if (i == 0)
                        break;
                    strVal = clo_getOptionString(option);
                    parse_file_name(strVal, tmp_file);
                    strcpy(input->ofile[i], tmp_file);
                    break;
                }
            }
            if (i >= MAX_OFILES) {
                HY1C_out("-E- l2gen_load_input: %s bigger than MAX_OFILES(%d)\n",
                        keyword, MAX_OFILES);
                return -1;
            }

        } else if (strcmp(keyword, "fmtofile") == 0) {
	    if (option->valStr)
	      strcpy(input->fmtofile[0], option->valStr);

        } else if (strcmp(keyword, "il2file") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->il2file[0], tmp_file);
            }

        } else if (strncmp(keyword, "il2file", 7) == 0) {
            for (i = 1; i < MAX_OFILES; i++) {
                sprintf(str_buf, "il2file%d", i + 1);
                if (strcmp(keyword, str_buf) == 0) {
                    if (i == 0)
                        break;
                    strVal = clo_getOptionString(option);
                    parse_file_name(strVal, tmp_file);
                    strcpy(input->il2file[i], tmp_file);
                    break;
                }
            }
            if (i >= MAX_OFILES) {
                HY1C_out("-E- l2gen_load_input: %s bigger than MAX_OFILES(%d)\n",
                        keyword, MAX_OFILES);
                return -1;
            }

        } else if (strcmp(keyword, "l2prod") == 0) {
            strArray = clo_getOptionStrings(option, &count);
            input->l2prod[0][0] = '\0';
            for (i = 0; i < count; i++) {
                if (i != 0)
                    strcat(input->l2prod[0], " ");
                strcat(input->l2prod[0], strArray[i]);
            }

        } else if (strncmp(keyword, "l2prod", 6) == 0) {
            for (i = 1; i < MAX_OFILES; i++) {
                sprintf(str_buf, "l2prod%d", i + 1);
                if (strcmp(keyword, str_buf) == 0) {
                    if (i == 0)
                        break;
                    strArray = clo_getOptionStrings(option, &count);
                    input->l2prod[i][0] = '\0';
                    for (j = 0; j < count; j++) {
                        if (j != 0)
                            strcat(input->l2prod[i], " ");
                        strcat(input->l2prod[i], strArray[j]);
                    }
                    break;
                }
            }
            if (i >= MAX_OFILES) {
                HY1C_out("-E- l2gen_load_input: %s bigger than MAX_OFILES(%d)\n",
                        keyword, MAX_OFILES);
                return -1;
            }

        } else if (strcmp(keyword, "pversion") == 0) {
            // if I copy it this way then spaces are allowed in the string
            if (option->valStr)
                strcpy(input->pversion, option->valStr);

        } else if (strcmp(keyword, "suite") == 0) {
            strcpy(input->suite, clo_getOptionString(option));

        } else if (strcmp(keyword, "eval") == 0) {
            input->evalmask = clo_getOptionInt(option);

        } else if (strcmp(keyword, "mode") == 0) {
            input->mode = clo_getOptionInt(option);

        } else if (strcmp(keyword, "spixl") == 0) {
            input->spixl = clo_getOptionInt(option);

        } else if (strcmp(keyword, "epixl") == 0) {
            input->epixl = clo_getOptionInt(option);

        } else if (strcmp(keyword, "dpixl") == 0) {
            input->dpixl = clo_getOptionInt(option);

        } else if (strcmp(keyword, "sline") == 0) {
            input->sline = clo_getOptionInt(option);

        } else if (strcmp(keyword, "eline") == 0) {
            input->eline = clo_getOptionInt(option);

        } else if (strcmp(keyword, "dline") == 0) {
            input->dline = clo_getOptionInt(option);

        } else if (strcmp(keyword, "ctl_pt_incr") == 0) {
            input->ctl_pt_incr = clo_getOptionInt(option);

        } else if (strcmp(keyword, "proc_ocean") == 0) {
            input->proc_ocean = clo_getOptionInt(option);

        } else if (strcmp(keyword, "proc_land") == 0) {
            input->proc_land = clo_getOptionBool(option);

        } else if (strcmp(keyword, "proc_sst") == 0) {
            input->proc_sst = clo_getOptionBool(option);

        } else if (strcmp(keyword, "atmocor") == 0) {
            input->atmocor = clo_getOptionBool(option);

        } else if (strcmp(keyword, "aer_opt") == 0) {
            input->aer_opt = clo_getOptionInt(option);

        } else if (strcmp(keyword, "aer_wave_short") == 0) {
            input->aer_wave_short = clo_getOptionInt(option);

        } else if (strcmp(keyword, "aer_wave_long") == 0) {
            input->aer_wave_long = clo_getOptionInt(option);

        } else if (strcmp(keyword, "aer_swir_short") == 0) {
            input->aer_swir_short = clo_getOptionInt(option);

        } else if (strcmp(keyword, "aer_swir_long") == 0) {
            input->aer_swir_long = clo_getOptionInt(option);

        } else if (strcmp(keyword, "aer_rrs_short") == 0) {
            input->aer_rrs_short = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "aer_rrs_long") == 0) {
            input->aer_rrs_long = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "aer_angstrom") == 0) {
            input->aer_angstrom = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "aer_iter_max") == 0) {
            input->aer_iter_max = clo_getOptionInt(option);

        } else if (strcmp(keyword, "seawater_opt") == 0) {
            input->seawater_opt = clo_getOptionInt(option);

        } else if (strcmp(keyword, "brdf_opt") == 0) {
            input->brdf_opt = clo_getOptionInt(option);

        } else if (strcmp(keyword, "gas_opt") == 0) {
            input->gas_opt = clo_getOptionInt(option);

        } else if (strcmp(keyword, "gsm_opt") == 0) {
            input->gsm_opt = clo_getOptionInt(option);

        } else if (strcmp(keyword, "gsm_fit") == 0) {
            input->gsm_fit = clo_getOptionInt(option);

        } else if (strcmp(keyword, "gsm_adg_s") == 0) {
            input->gsm_adg_s = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "gsm_bbp_s") == 0) {
            input->gsm_bbp_s = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "gsm_aphs") == 0) {
            fArray = clo_getOptionFloats(option, &count);
            if (count > NBANDS) {
                HY1C_out("-E- number of gsm_aphs elements (%d) must be %d or less\n", count, NBANDS);
                exit(1);
            }
            for (i = 0; i < count; i++)
                input->gsm_aphs[i] = fArray[i];
            for (; i < NBANDS; i++)
                input->gsm_aphs[i] = -1.0;

        } else if (strcmp(keyword, "gsm_aphw") == 0) {
            fArray = clo_getOptionFloats(option, &count);
            if (count > NBANDS) {
                HY1C_out("-E- number of gsm_aphw elements (%d) must be %d or less\n", count, NBANDS);
                exit(1);
            }
            for (i = 0; i < count; i++)
                input->gsm_aphw[i] = fArray[i];
            for (; i < NBANDS; i++)
                input->gsm_aphw[i] = -1.0;

        } else if (strcmp(keyword, "qaa_adg_s") == 0) {
            input->qaa_adg_s = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "qaa_wave") == 0) {
            if (clo_isOptionSet(option)) {
                iArray = clo_getOptionInts(option, &count);
                if (count > 5) {
                    HY1C_out("-E- number of qaa_wave elements must be 5 or less.\n");
                    exit(1);
                }
                for (i = 0; i < count; i++)
                    input->qaa_wave[i] = iArray[i];
            }

        } else if (strcmp(keyword, "giop_maxiter") == 0) {
            input->giop_maxiter = clo_getOptionInt(option);

        } else if (strcmp(keyword, "giop_fit_opt") == 0) {
            input->giop_fit_opt = clo_getOptionInt(option);

        } else if (strcmp(keyword, "giop_ts_opt") == 0) {
            input->giop_ts_opt = clo_getOptionInt(option);

        } else if (strcmp(keyword, "giop_aph_opt") == 0) {
            input->giop_aph_opt = clo_getOptionInt(option);

        } else if (strcmp(keyword, "giop_adg_opt") == 0) {
            input->giop_adg_opt = clo_getOptionInt(option);

        } else if (strcmp(keyword, "giop_bbp_opt") == 0) {
            input->giop_bbp_opt = clo_getOptionInt(option);

        } else if (strcmp(keyword, "giop_rrs_opt") == 0) {
            input->giop_rrs_opt = clo_getOptionInt(option);

        } else if (strcmp(keyword, "giop_aph_opt") == 0) {
            input->giop_aph_opt = clo_getOptionInt(option);

        } else if (strcmp(keyword, "giop_aph_file") == 0) {
            strVal = clo_getOptionString(option);
            parse_file_name(strVal, tmp_file);
            strcpy(input->giop_aph_file, tmp_file);

        } else if (strcmp(keyword, "giop_aph_s") == 0) {
            input->giop_aph_s = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "giop_adg_file") == 0) {
            strVal = clo_getOptionString(option);
            parse_file_name(strVal, tmp_file);
            strcpy(input->giop_adg_file, tmp_file);

        } else if (strcmp(keyword, "giop_adg_s") == 0) {
            input->giop_adg_s = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "giop_bbp_file") == 0) {
            strVal = clo_getOptionString(option);
            parse_file_name(strVal, tmp_file);
            strcpy(input->giop_bbp_file, tmp_file);

        } else if (strcmp(keyword, "giop_bbp_s") == 0) {
            input->giop_bbp_s = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "giop_grd") == 0) {
            fArray = clo_getOptionFloats(option, &count);
            if (count > 2) {
                HY1C_out("-E- number of giop_grd elements must be 2 or less.\n");
                exit(1);
            }
            for (i = 0; i < count; i++)
                input->giop_grd[i] = fArray[i];

        } else if (strcmp(keyword, "giop_wave") == 0) {
            if (clo_isOptionSet(option)) {
                fArray = clo_getOptionFloats(option, &count);
                if (count > NBANDS) {
                    HY1C_out("-E- number of giop_wave wavelengths must be %d or less\n", NBANDS);
                    exit(1);
                }
                for (i = 0; i < count; i++)
                    input->giop_wave[i] = fArray[i];
                for (; i < NBANDS; i++)
                    input->giop_wave[i] = -1.0;
            }

        } else if (strcmp(keyword, "giop_rrs_unc") == 0) {
            if (clo_isOptionSet(option)) {
                fArray = clo_getOptionFloats(option, &count);
                if (count > NBANDS) {
                    HY1C_out("-E- number of giop_rrs_unc must be %d or less\n", NBANDS);
                    exit(1);
                }
                for (i = 0; i < count; i++)
                    input->giop_rrs_unc[i] = fArray[i];
                for (; i < NBANDS; i++)
                    input->giop_rrs_unc[i] = -1.0;
            }

        } else if (strcmp(keyword, "iop_opt") == 0) {
            input->iop_opt = clo_getOptionInt(option);

        } else if (strcmp(keyword, "xcalfile") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->xcalfile, tmp_file);
            }

        } else if (strcmp(keyword, "xcal_opt") == 0) {
            if (clo_isOptionSet(option)) {
                iArray = clo_getOptionInts(option, &count);
                input->xcal_nwave = count;
                if (count > NBANDS) {
                    HY1C_out("-E- number of xcal_wave wavelengths must be %d or less\n", NBANDS);
                    // exit(1);
                    count = NBANDS;
                }
                for (i = 0; i < count; i++)
                    input->xcal_opt[i] = iArray[i];
            }

        } else if (strcmp(keyword, "xcal_wave") == 0) {
            if (clo_isOptionSet(option)) {
                fArray = clo_getOptionFloats(option, &count);
                input->xcal_nwave = count;
                if (count > NBANDS) {
                    HY1C_out("-E- number of xcal_wave wavelengths must be %d or less\n", NBANDS);
                    //exit(1);
                    count = NBANDS;
                }
                for (i = 0; i < count; i++)
                    input->xcal_wave[i] = fArray[i];
            }

        } else if (strcmp(keyword, "polfile") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->polfile, tmp_file);
            }

        } else if (strcmp(keyword, "pol_opt") == 0) {
            input->pol_opt = clo_getOptionInt(option);

        } else if (strcmp(keyword, "rad_opt") == 0) {
            input->rad_opt = clo_getOptionInt(option);

        } else if (strcmp(keyword, "ocrvc_opt") == 0) {
            input->ocrvc_opt = clo_getOptionInt(option);

        } else if (strcmp(keyword, "absaer_opt") == 0) {
            input->absaer_opt = clo_getOptionInt(option);

        } else if (strcmp(keyword, "sl_pixl") == 0) {
            input->sl_pixl = clo_getOptionInt(option);

        } else if (strcmp(keyword, "sl_frac") == 0) {
            input->sl_frac = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "resolution") == 0) {
            input->resolution = clo_getOptionInt(option);

        } else if (strcmp(keyword, "glint_opt") == 0) {
            input->glint_opt = clo_getOptionInt(option);

        } else if (strcmp(keyword, "outband_opt") == 0) {
            input->outband_opt = clo_getOptionInt(option);

        } else if (strcmp(keyword, "oxaband_opt") == 0) {
            input->oxaband_opt = clo_getOptionBool(option);

        } else if (strcmp(keyword, "filter_opt") == 0) {
            if (clo_isOptionSet(option))
                input->filter_opt = clo_getOptionBool(option);

        } else if (strcmp(keyword, "filter_file") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->filter_file, tmp_file);
            }

        } else if (strcmp(keyword, "tgtfile") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->tgtfile, tmp_file);
            }

        } else if (strcmp(keyword, "aerfile") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->aerfile, tmp_file);
            }

        } else if (strcmp(keyword, "btfile") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->btfile, tmp_file);
            }

        } else if (strcmp(keyword, "sstcoeffile") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->sstcoeffile, tmp_file);
            }

        } else if (strcmp(keyword, "sstssesfile") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->sstssesfile, tmp_file);
            }

        } else if (strcmp(keyword, "sstmirrfile") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->sstmirrfile, tmp_file);
            }

        } else if (strcmp(keyword, "sst4coeffile") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->sst4coeffile, tmp_file);
            }

        } else if (strcmp(keyword, "sst4ssesfile") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->sst4ssesfile, tmp_file);
            }

        } else if (strcmp(keyword, "sst4mirrfile") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->sst4mirrfile, tmp_file);
            }

        } else if (strcmp(keyword, "vcnnfile") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->vcnnfile, tmp_file);
            }

        } else if (strcmp(keyword, "owtfile") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->owtfile, tmp_file);
            }

        } else if (strcmp(keyword, "owtchlerrfile") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->owtchlerrfile, tmp_file);
            }

        } else if (strcmp(keyword, "metafile") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->metafile, tmp_file);
            }

        } else if (strcmp(keyword, "aerbinfile") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->aerbinfile, tmp_file);
            }

        } else if (strcmp(keyword, "met1") == 0) {
            strVal = clo_getOptionString(option);
            parse_file_name(strVal, tmp_file);
            strcpy(input->met1, tmp_file);

        } else if (strcmp(keyword, "met2") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->met2, tmp_file);
            }

        } else if (strcmp(keyword, "met3") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->met3, tmp_file);
            }

        } else if (strcmp(keyword, "ozone1") == 0) {
            strVal = clo_getOptionString(option);
            parse_file_name(strVal, tmp_file);
            strcpy(input->ozone1, tmp_file);

        } else if (strcmp(keyword, "ozone2") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->ozone2, tmp_file);
            }

        } else if (strcmp(keyword, "ozone3") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->ozone3, tmp_file);
            }

        } else if (strcmp(keyword, "land") == 0) {
            strVal = clo_getOptionString(option);
            parse_file_name(strVal, tmp_file);
            strcpy(input->land, tmp_file);

        } else if (strcmp(keyword, "water") == 0) {
            strVal = clo_getOptionString(option);
            parse_file_name(strVal, tmp_file);
            strcpy(input->water, tmp_file);

        } else if (strcmp(keyword, "demfile") == 0) {
            strVal = clo_getOptionString(option);
            parse_file_name(strVal, tmp_file);
            strcpy(input->demfile, tmp_file);

        } else if (strcmp(keyword, "icefile") == 0) {
            strVal = clo_getOptionString(option);
            parse_file_name(strVal, tmp_file);
            strcpy(input->icefile, tmp_file);

        } else if (strcmp(keyword, "sstfile") == 0) {
            strVal = clo_getOptionString(option);
            parse_file_name(strVal, tmp_file);
            strcpy(input->sstfile, tmp_file);

        } else if (strcmp(keyword, "sssfile") == 0) {
            strVal = clo_getOptionString(option);
            parse_file_name(strVal, tmp_file);
            strcpy(input->sssfile, tmp_file);

        } else if (strcmp(keyword, "no2file") == 0) {
            strVal = clo_getOptionString(option);
            parse_file_name(strVal, tmp_file);
            strcpy(input->no2file, tmp_file);

        } else if (strcmp(keyword, "alphafile") == 0) {
            strVal = clo_getOptionString(option);
            parse_file_name(strVal, tmp_file);
            strcpy(input->alphafile, tmp_file);

        } else if (strcmp(keyword, "tauafile") == 0) {
            strVal = clo_getOptionString(option);
            parse_file_name(strVal, tmp_file);
            strcpy(input->tauafile, tmp_file);

        } else if (strcmp(keyword, "geofile") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->geofile, tmp_file);
            }

        } else if (strcmp(keyword, "owmcfile") == 0) {
            strVal = clo_getOptionString(option);
            parse_file_name(strVal, tmp_file);
            strcpy(input->owmcfile, tmp_file);

        } else if (strcmp(keyword, "prodxmlfile") == 0) {
            if (clo_isOptionSet(option)) {
                strVal = clo_getOptionString(option);
                parse_file_name(strVal, tmp_file);
                strcpy(input->prodXMLfile, tmp_file);
            }

        } else if (strcmp(keyword, "gain") == 0) {
            if (clo_isOptionSet(option)) {
                fArray = clo_getOptionFloats(option, &count);
                if (count > NBANDS) {
                    HY1C_out("-E- number of gain elements must be %d or less\n", NBANDS);
                    count = NBANDS;
                    //exit(1);
                }
                for (i = 0; i < count; i++)
                    input->gain[i] = fArray[i];
                numGains = count;
            }

        } else if (strcmp(keyword, "gain_unc") == 0) {
            if (clo_isOptionSet(option)) {
                fArray = clo_getOptionFloats(option, &count);
                if (count > NBANDS) {
                    HY1C_out("-E- number of gain elements must be %d or less\n", NBANDS);
                    exit(1);
                }
                for (i = 0; i < count; i++)
                    input->gain_unc[i] = fArray[i];
                numGainUncs = count;
            }

        } else if (strcmp(keyword, "offset") == 0) {
            if (clo_isOptionSet(option)) {
                fArray = clo_getOptionFloats(option, &count);
                if (count > NBANDS) {
                    HY1C_out("-E- number of offset elements must be %d or less\n", NBANDS);
                    count = NBANDS;
                    //exit(1);
                }
                for (i = 0; i < count; i++)
                    input->offset[i] = fArray[i];
                numOffsets = count;
            }

        } else if (strcmp(keyword, "flaguse") == 0) {
            strArray = clo_getOptionStrings(option, &count);
            input->flaguse[0] = '\0';
            for (i = 0; i < count; i++) {
                if (i != 0)
                    strcat(input->flaguse, ",");
                strcat(input->flaguse, strArray[i]);
            }

        } else if (strcmp(keyword, "xcalbox") == 0) {
            input->xcalbox = clo_getOptionInt(option);

        } else if (strcmp(keyword, "xcalboxcenter") == 0) {
            iArray = clo_getOptionInts(option, &count);
            if (count > 2) {
                HY1C_out("-E- number of xcalboxcenter elements must be 2 or less\n");
                exit(1);
            }
            for (i = 0; i < count; i++)
                input->xcalboxcenter[i] = iArray[i];

        } else if (strcmp(keyword, "xcalpervalid") == 0) {
            input->xcalpervalid = clo_getOptionInt(option);

        } else if (strcmp(keyword, "xcalsubsmpl") == 0) {
            input->xcalsubsmpl = clo_getOptionInt(option);

        } else if (strcmp(keyword, "maxpointdist") == 0) {
            input->maxpointdist = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "chlthreshold") == 0) {
            input->chlthreshold = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "aotthreshold") == 0) {
            input->aotthreshold = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "coccolith") == 0) {
            fArray = clo_getOptionFloats(option, &count);
            if (count > 8) {
                HY1C_out("-E- number of coccolith elements must be 8 or less\n");
                exit(1);
            }
            for (i = 0; i < count; i++)
                input->coccolith[i] = fArray[i];

        } else if (strcmp(keyword, "cirrus_thresh") == 0) {
            fArray = clo_getOptionFloats(option, &count);
            if (count > 2) {
                HY1C_out("-E- number of cirrus_thresh elements must be 2 or less\n");
                exit(1);
            }
            for (i = 0; i < count; i++)
                input->cirrus_thresh[i] = fArray[i];

        } else if (strcmp(keyword, "chloc2_wave") == 0) {
            iArray = clo_getOptionInts(option, &count);
            if (count > 2) {
                HY1C_out("-E- number of chloc2_wave elements must be 2 or less\n");
                exit(1);
            }
            for (i = 0; i < count; i++)
                input->chloc2w[i] = iArray[i];

        } else if (strcmp(keyword, "chloc2_coef") == 0) {
            fArray = clo_getOptionFloats(option, &count);
            if (count > 5) {
                HY1C_out("-E- number of chloc2_coef elements must be 5 or less\n");
                exit(1);
            }
            for (i = 0; i < count; i++)
                input->chloc2c[i] = fArray[i];

        } else if (strcmp(keyword, "chloc3_wave") == 0) {
            iArray = clo_getOptionInts(option, &count);
            if (count > 3) {
                HY1C_out("-E- number of chloc3_wave elements must be 3 or less\n");
                exit(1);
            }
            for (i = 0; i < count; i++)
                input->chloc3w[i] = iArray[i];

        } else if (strcmp(keyword, "chloc3_coef") == 0) {
            fArray = clo_getOptionFloats(option, &count);
            if (count > 5) {
                HY1C_out("-E- number of chloc3_coef elements must be 5 or less\n");
                exit(1);
            }
            for (i = 0; i < count; i++)
                input->chloc3c[i] = fArray[i];

        } else if (strcmp(keyword, "chloc4_wave") == 0) {
            iArray = clo_getOptionInts(option, &count);
            if (count > 4) {
                HY1C_out("-E- number of chloc4_wave elements must be 4 or less\n");
                exit(1);
            }
            for (i = 0; i < count; i++)
                input->chloc4w[i] = iArray[i];

        } else if (strcmp(keyword, "chloc4_coef") == 0) {
            fArray = clo_getOptionFloats(option, &count);
            if (count > 5) {
                HY1C_out("-E- number of chloc4_coef elements must be 5 or less\n");
                exit(1);
            }
            for (i = 0; i < count; i++)
                input->chloc4c[i] = fArray[i];

        } else if (strcmp(keyword, "chlclark_wave") == 0) {
            iArray = clo_getOptionInts(option, &count);
            if (count > 3) {
                HY1C_out("-E- number of chlclark_wave elements must be 3 or less\n");
                exit(1);
            }
            for (i = 0; i < count; i++)
                input->chlclarkw[i] = iArray[i];

        } else if (strcmp(keyword, "chlclark_coef") == 0) {
            fArray = clo_getOptionFloats(option, &count);
            if (count > 6) {
                HY1C_out("-E- number of chlclark_coef elements must be 6 or less\n");
                exit(1);
            }
            for (i = 0; i < count; i++)
                input->chlclarkc[i] = fArray[i];

        } else if (strcmp(keyword, "kd2_wave") == 0) {
            iArray = clo_getOptionInts(option, &count);
            if (count > 2) {
                HY1C_out("-E- number of kd2_wave elements must be 2 or less\n");
                exit(1);
            }
            for (i = 0; i < count; i++)
                input->kd2w[i] = iArray[i];

        } else if (strcmp(keyword, "kd2_coef") == 0) {
            fArray = clo_getOptionFloats(option, &count);
            if (count > 6) {
                HY1C_out("-E- number of kd2_coef elements must be 6 or less\n");
                exit(1);
            }
            for (i = 0; i < count; i++)
                input->kd2c[i] = fArray[i];

        } else if (strcmp(keyword, "flh_offset") == 0) {
            input->flh_offset = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "aermodels") == 0) {
            strArray = clo_getOptionStrings(option, &count);
            if (count > MAXAERMOD) {
                HY1C_out("-E- number of aermodels must be %d or less\n",
                        MAXAERMOD);
                exit(1);
            }
            for (i = 0; i < count; i++)
                strcpy(input->aermodels[i], strArray[i]);
            for (; i < MAXAERMOD; i++)
                input->aermodels[i][0] = '\0';
            input->naermodels = count;

        } else if (strcmp(keyword, "taua") == 0) {
            if (clo_isOptionSet(option)) {
                fArray = clo_getOptionFloats(option, &count);
                if (count > NBANDS) {
                    HY1C_out("-E- number of taua elements must be %d or less\n",
                            NBANDS);
                    exit(1);
                }
                for (i = 0; i < count; i++)
                    input->taua[i] = fArray[i];
                numTauas = count;
            }

        } else if (strcmp(keyword, "aermodrat") == 0) {
            input->aermodrat = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "aermodmin") == 0) {
            input->aermodmin = clo_getOptionInt(option);

        } else if (strcmp(keyword, "aermodmax") == 0) {
            input->aermodmax = clo_getOptionInt(option);

        } else if (strcmp(keyword, "absaer") == 0) {
            input->absaer = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "rhoamin") == 0) {
            input->rhoamin = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "cloud_eps") == 0) {
            input->cloud_eps = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "cloud_thresh") == 0) {
            input->albedo = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "cloud_wave") == 0) {
            input->cloud_wave = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "glint_thresh") == 0) {
            input->glint = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "sunzen") == 0) {
            input->sunzen = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "satzen") == 0) {
            input->satzen = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "epsmin") == 0) {
            input->epsmin = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "epsmax") == 0) {
            input->epsmax = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "tauamax") == 0) {
            input->tauamax = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "nlwmin") == 0) {
            input->nlwmin = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "hipol") == 0) {
            input->hipol = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "wsmax") == 0) {
            input->wsmax = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "windspeed") == 0) {
            input->windspeed = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "windangle") == 0) {
            input->windangle = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "pressure") == 0) {
            input->pressure = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "ozone") == 0) {
            input->ozone = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "relhumid") == 0) {
            input->relhumid = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "watervapor") == 0) {
            input->watervapor = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "ice_threshold") == 0) {
            input->ice_threshold = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "maskland") == 0) {
            input->landmask = clo_getOptionBool(option);

        } else if (strcmp(keyword, "maskbath") == 0) {
            input->bathmask = clo_getOptionBool(option);

        } else if (strcmp(keyword, "maskcloud") == 0) {
            input->cloudmask = clo_getOptionBool(option);

        } else if (strcmp(keyword, "maskglint") == 0) {
            input->glintmask = clo_getOptionBool(option);

        } else if (strcmp(keyword, "masksunzen") == 0) {
            input->sunzenmask = clo_getOptionBool(option);

        } else if (strcmp(keyword, "masksatzen") == 0) {
            input->satzenmask = clo_getOptionBool(option);

        } else if (strcmp(keyword, "maskhilt") == 0) {
            input->hiltmask = clo_getOptionBool(option);

        } else if (strcmp(keyword, "maskstlight") == 0) {
            input->stlightmask = clo_getOptionBool(option);

        } else if (strcmp(keyword, "mumm_alpha") == 0) {
            input->mumm_alpha = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "mumm_gamma") == 0) {
            input->mumm_gamma = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "mumm_epsilon") == 0) {
            input->mumm_epsilon = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "degc") == 0) {
            input->degc = clo_getOptionInt(option);

        } else if (strcmp(keyword, "vcal_opt") == 0) {
            input->vcal_opt = clo_getOptionInt(option);

        } else if (strcmp(keyword, "vcal_nlw") == 0) {
            if (clo_isOptionSet(option)) {
                fArray = clo_getOptionFloats(option, &count);
                if (count > NBANDS) {
                    HY1C_out("-E- number of vcal_nLw elements must be %d or less\n",
                            NBANDS);
                    exit(1);
                }
                for (i = 0; i < count; i++)
                    input->vcal_nLw[i] = fArray[i];
                if (input->vcal_opt < 0)
                    input->vcal_opt = INVERSE_NLW;
            }

        } else if (strcmp(keyword, "vcal_lw") == 0) {
            if (clo_isOptionSet(option)) {
                fArray = clo_getOptionFloats(option, &count);
                if (count > NBANDS) {
                    HY1C_out("-E- number of vcal_Lw elements must be %d or less\n",
                            NBANDS);
                    exit(1);
                }
                for (i = 0; i < count; i++)
                    input->vcal_Lw[i] = fArray[i];
                if (input->vcal_opt < 0)
                    input->vcal_opt = INVERSE_LW;
            }

        } else if (strcmp(keyword, "vcal_chl") == 0) {
            input->vcal_chl = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "vcal_solz") == 0) {
            input->vcal_solz = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "vct_msk_water") == 0) {
            input->vct_msk_water = clo_getOptionInt(option);

        } else if (strcmp(keyword, "vct_water") == 0) {
            strVal = clo_getOptionString(option);
            parse_file_name(strVal, tmp_file);
            strcpy(input->vct_water, tmp_file);

        } else if (strcmp(keyword, "vct_min_nbin") == 0) {
            input->vct_min_nbin = clo_getOptionInt(option);

        } else if (strcmp(keyword, "vct_fill_pct") == 0) {
            input->vct_fill_pct = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "stype") == 0) {
            input->stype = clo_getOptionInt(option);

        } else if (strcmp(keyword, "datamin") == 0) {
            input->datamin = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "datamax") == 0) {
            input->datamax = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "west") == 0) {
            input->west = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "east") == 0) {
            input->east = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "north") == 0) {
            input->north = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "south") == 0) {
            input->south = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "width") == 0) {
            input->width = clo_getOptionInt(option);

        } else if (strcmp(keyword, "threshold") == 0) {
            input->threshold = clo_getOptionFloat(option);

        } else if (strcmp(keyword, "rgb") == 0) {
            if (clo_isOptionSet(option)) {
                iArray = clo_getOptionInts(option, &count);
                if (count != 3) {
                    HY1C_out("-E- number of rgb elements must be 3\n");
                    exit(1);
                }
                for (i = 0; i < count; i++)
                    input->rgb[i] = iArray[i];
            }

        } else if (strcmp(keyword, "subsamp") == 0) {
            input->subsamp = clo_getOptionInt(option);

        } else if (strcmp(keyword, "outmode") == 0) {
            strVal = clo_getOptionString(option);
            if (!strcmp(mainProgramName, "l1mapgen")) {
                if(!strcmp(strVal, "0")) {
                    input->outmode = 0;
                } else if(!strcmp(strVal, "1")) {
                    input->outmode = 1;
                } else if(!strcmp(strVal, "2")) {
                    input->outmode = 2;
                } else if(!strcasecmp(strVal, "ppm")) {
                    input->outmode = 0;
                } else if(!strcasecmp(strVal, "png")) {
                    input->outmode = 1;
                } else if(!strcasecmp(strVal, "tiff")) {
                    input->outmode = 2;
                } else {
                    HY1C_out("-E- Invalid value for outmode=\"%s\"\n", strVal);
                    clo_dumpOption(option);
                    exit(1);
                }
            } else {
                if(!strcmp(strVal, "0")) {
                    input->outmode = 0;
                } else if(!strcmp(strVal, "1")) {
                    input->outmode = 1;
                } else if(!strcmp(strVal, "2")) {
                    input->outmode = 2;
                } else if(!strcmp(strVal, "3")) {
                    input->outmode = 3;
                } else if(!strcmp(strVal, "4")) {
                    input->outmode = 4;
                } else if(!strcasecmp(strVal, "8bit")) {
                    input->outmode = 0;
                } else if(!strcasecmp(strVal, "24bit")) {
                    input->outmode = 1;
                } else if(!strcasecmp(strVal, "ppm")) {
                    input->outmode = 2;
                } else if(!strcasecmp(strVal, "bin")) {
                    input->outmode = 3;
                } else if(!strcasecmp(strVal, "png")) {
                    input->outmode = 4;
                } else {
                    HY1C_out("-E- Invalid value for outmode=\"%s\"\n", strVal);
                    clo_dumpOption(option);
                    exit(1);
                }
            }            

        } else if (strcmp(keyword, "xbox") == 0) {
            input->xbox = clo_getOptionInt(option);

        } else if (strcmp(keyword, "ybox") == 0) {
            input->ybox = clo_getOptionInt(option);

        } else {
            HY1C_out("-E- Invalid argument \"%s\"\n", keyword);
            clo_dumpOption(option);
            exit(1);
        }

    } // for optionIDs

    return 0;
}

int msl12_option_input(int argc, char **argv, clo_optionList_t* list,
        char *progName, instr *input, filehandle *l1file) {
    int i;
    char *tmp_str;
    char str_buf[FILENAME_MAX] = "";

    /* For reading sensor table */
    int32_t numBands = g_cfg.hy1c_nwave; // Felix TODO

    /* read the command line options, default, sensor, sub-sensor 
       and suite par files.  set elements of l1file */
    if (l2gen_read_options(list, progName, argc, argv, l1file) != 0) {
        HY1C_out("-E- %s: Error reading program options.\n", __FILE__);
    }

    // add more info into the input structure
    input->sensorID = 9;
    input->subsensorID = -1;
    input->format = 13;
    input->modis_subset_compat = 0;

    //    /*                                                                  */
    //    /* Now, loop through command arguments again and update input struct*/
    //    /*                                                                  */
    //    strcpy(input->pro_control, argv[0]);
    //    for (i = 1; i < argc; i++) {
    //        strcat(input->pro_control, " ");
    //        strcat(input->pro_control, argv[i]);
    //    }

    if (l2gen_load_input(list, input) != 0) {
        HY1C_out("-E- %s: Error loading options into input structure.\n", __FILE__);
        return (-1);
    }

    //    l1file->geofile = input->geofile;
    //    l1file->calfile = input->calfile;
    //    l1file->input = input;
    if (input->resolution == -1000)
        input->resolution = 1000;

    //    if ((tmp_str = getenv("OCDATAROOT")) == NULL) {
    //        HY1C_out("OCDATAROOT environment variable is not defined.\n");
    //        return (1);
    //    }

#if 0
    /* Load filter list, if filtering requested */
    if (input->filter_opt == 1) {
        if (input->filter_file[0] == '\0') {
            sprintf(input->filter_file, "%s/%s/%s_filter.dat", tmp_str,
                    "HY1C", "msl12");
        }
        sprintf(input->filter_file, "%s/%s/%s_filter.dat", tmp_str,
                "HY1C", "msl12");
        rdfilter(input->filter_file, &(input->fctl));
    }
#endif

    /*                                                                  */
    /* Build string of input parameters for meta-data documentation     */
    /*                                                                  */

    strcat(input->input_parms, "\n");
    for (i = 0; i < MAX_IFILES; i++) {

        if (input->ifile[i][0] != '\0') {
            sprintf(str_buf, "IFILE%d = %s ", i + 1, input->ifile[i]);

            strcat(input->input_parms, str_buf);
            strcat(input->input_parms, "\n");
        } else break;
    }

    for (i = 0; i < MAX_OFILES; i++) {

        if (input->ofile[i][0] != '\0') {
            sprintf(str_buf, "OFILE%d = %s", i + 1, input->ofile[i]);

            strcat(input->input_parms, str_buf);
            strcat(input->input_parms, "\n");
        }

        if (input->fmtofile[i][0] != '\0') {
            sprintf(str_buf, "FMTOFILE%d = %s", i + 1, input->fmtofile[i]);

            strcat(input->input_parms, str_buf);
            strcat(input->input_parms, "\n");
        }

        if (input->l2prod[i][0] != '\0') {
            sprintf(str_buf, "L2PROD%d = %s", i + 1, input->l2prod[i]);

            strcat(input->input_parms, str_buf);
            strcat(input->input_parms, "\n");
        }

        if (input->mode != FORWARD && input->il2file[i][0] != '\0') {
            sprintf(str_buf, "IL2FILE%d = %s", i + 1, input->il2file[i]);

            strcat(input->input_parms, str_buf);
            strcat(input->input_parms, "\n");
        }

    }

    sprintf(str_buf, "CALFILE = %s", input->calfile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "CLDFILE = %s", input->cldfile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GEOFILE = %s", input->geofile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "METAFILE = %s", input->metafile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    if (input->mode != FORWARD) {

        sprintf(str_buf, "FLAGUSE = %s", input->flaguse);
        strcat(input->input_parms, str_buf);
        strcat(input->input_parms, "\n");

        sprintf(str_buf, "MAXPOINTDIST = %8.3f", input->maxpointdist);
        strcat(input->input_parms, str_buf);
        strcat(input->input_parms, "\n");

        sprintf(str_buf, "CHLTHRESHOLD  = %8.3f", input->chlthreshold);
        strcat(input->input_parms, str_buf);
        strcat(input->input_parms, "\n");

        sprintf(str_buf, "AOTTHRESHOLD  = %8.3f", input->aotthreshold);
        strcat(input->input_parms, str_buf);
        strcat(input->input_parms, "\n");

        sprintf(str_buf, "XCALBOX = %d", (int) input->xcalbox);
        strcat(input->input_parms, str_buf);
        strcat(input->input_parms, "\n");

        sprintf(str_buf, "XCALBOXCENTER = %d, %d",
                (int) input->xcalboxcenter[0], (int) input->xcalboxcenter[1]);
        strcat(input->input_parms, str_buf);
        strcat(input->input_parms, "\n");

        sprintf(str_buf, "XCALPERVALID = %d", (int) input->xcalpervalid);
        strcat(input->input_parms, str_buf);
        strcat(input->input_parms, "\n");

        sprintf(str_buf, "XCALSUBSMPL = %d", (int) input->xcalsubsmpl);
        strcat(input->input_parms, str_buf);
        strcat(input->input_parms, "\n");

    }

    sprintf(str_buf, "PVERSION = %s", input->pversion);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "SUITE = %s", input->suite);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "EVAL = %5d", input->evalmask);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "MODE = %5d", input->mode);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "SPIXL = %5d", input->spixl);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "EPIXL = %5d", input->epixl);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "DPIXL = %5d", input->dpixl);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "SLINE = %5d", input->sline);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "ELINE = %5d", input->eline);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "DLINE = %5d", input->dline);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "CTL_PT_INCR = %5d", input->ctl_pt_incr);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "PROC_OCEAN = %3d", input->proc_ocean);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "PROC_LAND = %3d", input->proc_land);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "PROC_SST = %3d", input->proc_sst);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "ATMOCOR = %3d", input->atmocor);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "SEAWATER_OPT = %3d", input->seawater_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "AER_OPT = %3d", input->aer_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "AER_WAVE_SHORT = %3d", input->aer_wave_short);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "AER_WAVE_LONG = %3d", input->aer_wave_long);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "AER_SWIR_SHORT = %3d", input->aer_swir_short);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "AER_SWIR_LONG = %3d", input->aer_swir_long);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "AER_RRS_SHORT = %8.5f", input->aer_rrs_short);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "AER_RRS_LONG = %8.5f", input->aer_rrs_long);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "AER_ANGSTROM = %8.5f", input->aer_angstrom);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "AER_ITER_MAX = %3d", input->aer_iter_max);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "BRDF_OPT = %3d", input->brdf_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GAS_OPT = %3d", input->gas_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "IOP_OPT = %3d", input->iop_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GSM_OPT = %3d", input->gsm_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GSM_FIT = %3d", input->gsm_fit);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GSM_ADG_S  = %8.5f", input->gsm_adg_s);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GSM_BBP_S  = %8.5f", input->gsm_bbp_s);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GSM_APHW = %8.5f", input->gsm_aphw[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < numBands; i++) {
        sprintf(str_buf, ", %8.5f", input->gsm_aphw[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GSM_APHS = %8.5f", input->gsm_aphs[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < numBands; i++) {
        sprintf(str_buf, ", %8.5f", input->gsm_aphs[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "QAA_ADG_S  = %8.5f", input->qaa_adg_s);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "QAA_WAVE = %4d", input->qaa_wave[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < 5; i++) {
        sprintf(str_buf, ", %4d", input->qaa_wave[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GIOP_MAXITER = %3d", input->giop_maxiter);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GIOP_FIT_OPT = %3d", input->giop_fit_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GIOP_TS_OPT = %3d", input->giop_ts_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GIOP_APH_OPT = %3d", input->giop_aph_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GIOP_ADG_OPT = %3d", input->giop_adg_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GIOP_BBP_OPT = %3d", input->giop_bbp_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GIOP_RRS_OPT = %3d", input->giop_rrs_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GIOP_APH_FILE = %s", input->giop_aph_file);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GIOP_APH_S  = %8.5f", input->giop_aph_s);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GIOP_ADG_FILE = %s", input->giop_adg_file);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GIOP_ADG_S  = %8.5f", input->giop_adg_s);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GIOP_BBP_FILE = %s", input->giop_bbp_file);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GIOP_BBP_S  = %8.5f", input->giop_bbp_s);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GIOP_GRD = %8.5f", input->giop_grd[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < 2; i++) {
        sprintf(str_buf, ", %8.5f", input->giop_grd[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GIOP_WAVE = %6.1f", input->giop_wave[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < NBANDS; i++) {
        sprintf(str_buf, ", %6.1f", input->giop_wave[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GIOP_RRS_UNC = %6.1f", input->giop_rrs_unc[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < NBANDS; i++) {
        sprintf(str_buf, ", %6.1f", input->giop_rrs_unc[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "POLFILE = %s", input->polfile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "POL_OPT = %3d", input->pol_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "RAD_OPT = %3d", input->rad_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "OCRVC_OPT = %3d", input->ocrvc_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "VCNNFILE = %s", input->vcnnfile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "ABSAER_OPT = %3d", input->absaer_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "SL_PIXL = %3d", input->sl_pixl);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "SL_FRAC = %8.4f", input->sl_frac);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GLINT_OPT = %3d", input->glint_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "RESOLUTION = %3d", input->resolution);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "OUTBAND_OPT = %3d", input->outband_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "OXABAND_OPT = %3d", input->oxaband_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "FILTER_OPT = %3d", input->filter_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");
    if (input->filter_opt == 1) {
        sprintf(str_buf, "FILTER_FILE = %s", input->filter_file);
        strcat(input->input_parms, str_buf);
        strcat(input->input_parms, "\n");
        for (i = 0; i < input->fctl.nfilt; i++) {
            sprintf(str_buf, "# FILTER_%d = %d x %d (%d) %s %d ",
                    i + 1,
                    input->fctl.f[i].nx,
                    input->fctl.f[i].ny,
                    input->fctl.f[i].minfill,
                    filter_names[input->fctl.f[i].func],
                    input->fctl.f[i].band + 1);
            strcat(input->input_parms, str_buf);
            strcat(input->input_parms, "\n");
        }
    }

    sprintf(str_buf, "AERFILE = %s", input->aerfile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "TGTFILE = %s", input->tgtfile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "MET1 = %s", input->met1);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "MET2 = %s", input->met2);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "MET3 = %s", input->met3);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "OZONE1 = %s", input->ozone1);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "OZONE2 = %s", input->ozone2);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "OZONE3 = %s", input->ozone3);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "LAND = %s", input->land);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "WATER = %s", input->water);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "DEMFILE = %s", input->demfile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "ICEFILE = %s", input->icefile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "SSTFILE = %s", input->sstfile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "SSSFILE = %s", input->sssfile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "NO2FILE = %s", input->no2file);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "ALPHAFILE = %s", input->alphafile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "TAUAFILE = %s", input->tauafile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "OWMCFILE = %s", input->owmcfile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "PRODXMLFILE = %s", input->prodXMLfile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "AERBINFILE = %s", input->aerbinfile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GAIN = %8.4f", input->gain[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < numBands; i++) {
        sprintf(str_buf, ", %8.4f", input->gain[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GAIN_UNC = %8.4f", input->gain_unc[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < numBands; i++) {
        sprintf(str_buf, ", %8.6f", input->gain_unc[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "OFFSET = %8.5f", input->offset[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < numBands; i++) {
        sprintf(str_buf, ", %8.5f", input->offset[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "NAERMODELS = %d", input->naermodels);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "AERMODELS = %3s", input->aermodels[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < input->naermodels; i++) {
        sprintf(str_buf, ", %3s", input->aermodels[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "TAUA = %8.4f", input->taua[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < numBands; i++) {
        sprintf(str_buf, ", %8.4f", input->taua[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "AERMODRAT = %8.5f", input->aermodrat);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "AERMODMIN = %3d", input->aermodmin);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "AERMODMAX = %3d", input->aermodmax);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "CLOUD_WAVE = %8.3f", input->cloud_wave);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "CLOUD_THRESH = %8.3f", input->albedo);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "CLOUD_EPS = %8.3f", input->cloud_eps);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "CIRRUS_THRESH = %8.5f, %8.5f", input->cirrus_thresh[0], input->cirrus_thresh[1]);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "ABSAER = %8.3f", input->absaer);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "RHOAMIN  = %8.5f", input->rhoamin);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "NLWMIN  = %8.3f", input->nlwmin);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "HIPOL  = %8.3f", input->hipol);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "WSMAX  = %8.3f", input->wsmax);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "COCCOLITH = %8.4f", input->coccolith[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < 8; i++) {
        sprintf(str_buf, ", %8.4f", input->coccolith[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "TAUAMAX  = %8.3f", input->tauamax);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "EPSMIN  = %8.3f", input->epsmin);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "EPSMAX  = %8.3f", input->epsmax);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "GLINT_THRESH = %8.3f", input->glint);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "WINDSPEED = %8.3f", input->windspeed);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "WINDANGLE = %8.3f", input->windangle);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "PRESSURE = %8.3f", input->pressure);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "OZONE = %8.3f", input->ozone);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "WATERVAPOR = %8.3f", input->watervapor);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "RELHUMID = %8.3f", input->relhumid);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "ICE_THRESHOLD = %8.3f", input->ice_threshold);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "SUNZEN = %8.3f", input->sunzen);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "SATZEN = %8.3f", input->satzen);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "MASKLAND = %2d", input->landmask);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "MASKBATH = %2d", input->bathmask);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "MASKCLOUD = %2d", input->cloudmask);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "MASKGLINT = %2d", input->glintmask);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "MASKSUNZEN = %2d", input->sunzenmask);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "MASKSATZEN = %2d", input->satzenmask);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "MASKHILT = %2d", input->hiltmask);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "MASKSTLIGHT = %2d", input->stlightmask);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "MUMM_ALPHA = %8.3f", input->mumm_alpha);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "MUMM_GAMMA = %8.3f", input->mumm_gamma);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "MUMM_EPSILON = %8.3f", input->mumm_epsilon);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "CHLOC2_WAVE = %4d", input->chloc2w[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < 2; i++) {
        sprintf(str_buf, ", %4d", input->chloc2w[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "CHLOC2_COEF = %8.5f", input->chloc2c[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < 5; i++) {
        sprintf(str_buf, ", %8.5f", input->chloc2c[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "CHLOC3_WAVE = %4d", input->chloc3w[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < 3; i++) {
        sprintf(str_buf, ", %4d", input->chloc3w[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "CHLOC3_COEF = %8.5f", input->chloc3c[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < 5; i++) {
        sprintf(str_buf, ", %8.5f", input->chloc3c[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "CHLOC4_WAVE = %4d", input->chloc4w[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < 4; i++) {
        sprintf(str_buf, ", %4d", input->chloc4w[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "CHLOC4_COEF = %8.5f", input->chloc4c[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < 5; i++) {
        sprintf(str_buf, ", %8.5f", input->chloc4c[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "CHLCLARK_WAVE = %4d", input->chlclarkw[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < 3; i++) {
        sprintf(str_buf, ", %4d", input->chlclarkw[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "CHLCLARK_COEF = %8.5f", input->chlclarkc[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < 6; i++) {
        sprintf(str_buf, ", %8.5f", input->chlclarkc[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "KD2_WAVE = %4d", input->kd2w[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < 2; i++) {
        sprintf(str_buf, ", %4d", input->kd2w[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "KD2_COEF = %8.5f", input->kd2c[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < 6; i++) {
        sprintf(str_buf, ", %8.5f", input->kd2c[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "FLH_OFFSET = %8.5f", input->flh_offset);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "DEGC = %3d", input->degc);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "BTFILE = %s", input->btfile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "SSTCOEFFILE = %s", input->sstcoeffile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "SSTSSESFILE = %s", input->sstssesfile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "SSTMIRRFILE = %s", input->sstmirrfile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "SST4COEFFILE = %s", input->sst4coeffile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "SST4SSESFILE = %s", input->sst4ssesfile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "SST4MIRRFILE = %s", input->sst4mirrfile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "VCAL_OPT = %3d", input->vcal_opt);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "VCAL_NLW = %8.4f", input->vcal_nLw[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < numBands; i++) {
        sprintf(str_buf, ", %8.4f", input->vcal_nLw[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "VCAL_LW = %8.4f", input->vcal_Lw[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < numBands; i++) {
        sprintf(str_buf, ", %8.4f", input->vcal_Lw[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "VCAL_CHL = %8.4f", input->vcal_chl);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "VCAL_SOLZ = %8.4f", input->vcal_solz);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "XCALFILE = %s", input->xcalfile);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "XCAL_OPT = %3d", input->xcal_opt[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < input->xcal_nwave; i++) {
        sprintf(str_buf, ", %3d", input->xcal_opt[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");
    sprintf(str_buf, "XCAL_WAVE = %8.4f", input->xcal_wave[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < input->xcal_nwave; i++) {
        sprintf(str_buf, ", %8.4f", input->xcal_wave[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "STYPE = %d", input->stype);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "DATAMIN = %8.4f", input->datamin);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "DATAMAX = %8.4f", input->datamax);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "NORTH = %8.4f", input->north);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "SOUTH = %8.4f", input->south);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "EAST = %8.4f", input->east);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "WEST = %8.4f", input->west);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "XBOX = %d", input->xbox);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "YBOX = %d", input->ybox);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "WIDTH = %d", input->width);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "THRESHOLD = %8.4f", input->threshold);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "RGB = %d", input->rgb[0]);
    strcat(input->input_parms, str_buf);
    for (i = 1; i < 3; i++) {
        sprintf(str_buf, ", %d", input->rgb[i]);
        strcat(input->input_parms, str_buf);
    }
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "SUBSAMP = %d", input->subsamp);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    sprintf(str_buf, "OUTMODE = %d", input->outmode);
    strcat(input->input_parms, str_buf);
    strcat(input->input_parms, "\n");

    /*                                                                  */
    /* Build string of input files for meta-data documentation          */
    /*                                                                  */
    for (i = 0; i < MAX_IFILES; i++) {
        if (input->ifile[i][0] != '\0') {
            tmp_str = strrchr(input->ifile[i], '/');
            tmp_str = (tmp_str == 0x0) ? input->ifile[i] : tmp_str + 1;
            if (i == 0) sprintf(input->input_files, "%s,", tmp_str);
            else {
                sprintf(str_buf, "%s,", tmp_str);
                strcat(input->input_files, str_buf);
            }
        } else break;
    }

    tmp_str = strrchr(input->met1, '/');
    tmp_str = (tmp_str == 0x0) ? input->met1 : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->met2, '/');
    tmp_str = (tmp_str == 0x0) ? input->met2 : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->met3, '/');
    tmp_str = (tmp_str == 0x0) ? input->met3 : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->ozone1, '/');
    tmp_str = (tmp_str == 0x0) ? input->ozone1 : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->ozone2, '/');
    tmp_str = (tmp_str == 0x0) ? input->ozone2 : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->ozone3, '/');
    tmp_str = (tmp_str == 0x0) ? input->ozone3 : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->calfile, '/');
    tmp_str = (tmp_str == 0x0) ? input->calfile : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->xcalfile, '/');
    tmp_str = (tmp_str == 0x0) ? input->xcalfile : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->polfile, '/');
    tmp_str = (tmp_str == 0x0) ? input->polfile : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->vcnnfile, '/');
    tmp_str = (tmp_str == 0x0) ? input->vcnnfile : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->cldfile, '/');
    tmp_str = (tmp_str == 0x0) ? input->cldfile : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->land, '/');
    tmp_str = (tmp_str == 0x0) ? input->land : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->water, '/');
    tmp_str = (tmp_str == 0x0) ? input->water : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->demfile, '/');
    tmp_str = (tmp_str == 0x0) ? input->demfile : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->icefile, '/');
    tmp_str = (tmp_str == 0x0) ? input->icefile : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->sstfile, '/');
    tmp_str = (tmp_str == 0x0) ? input->sstfile : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->sssfile, '/');
    tmp_str = (tmp_str == 0x0) ? input->sssfile : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->no2file, '/');
    tmp_str = (tmp_str == 0x0) ? input->no2file : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->alphafile, '/');
    tmp_str = (tmp_str == 0x0) ? input->alphafile : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->tauafile, '/');
    tmp_str = (tmp_str == 0x0) ? input->tauafile : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->geofile, '/');
    tmp_str = (tmp_str == 0x0) ? input->geofile : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    tmp_str = strrchr(input->owmcfile, '/');
    tmp_str = (tmp_str == 0x0) ? input->owmcfile : tmp_str + 1;
    sprintf(str_buf, "%s,", tmp_str);
    strcat(input->input_files, str_buf);

    /*                                                                  */
    /* Build string of mask names for meta-data documentation           */
    /*                                                                  */
    strcpy(input->mask_names, "ATMFAIL");
    if (input->landmask == 1) strcat(input->mask_names, ",LAND");
    if (input->bathmask == 1) strcat(input->mask_names, ",COASTZ");
    if (input->cloudmask == 1) strcat(input->mask_names, ",CLDICE");
    if (input->glintmask == 1) strcat(input->mask_names, ",HIGLINT");
    if (input->sunzenmask == 1) strcat(input->mask_names, ",HISOLZEN");
    if (input->satzenmask == 1) strcat(input->mask_names, ",HISATZEN");
    if (input->hiltmask == 1) strcat(input->mask_names, ",HILT");
    if (input->stlightmask == 1) strcat(input->mask_names, ",STRAYLIGHT");

    return 0;
}

/*-----------------------------------------------------------------------------
    Function:  msl12_input

    Returns:   int (status)
        The return code is a negative value if any error occurs, otherwise,
        returns 0.

    Description:
        Convert the arguments from the command line into a structure input
        variable.

    Parameters: (in calling order)
        Type      Name         I/O   Description
        ----      ----         ---   -----------
        int       argc          I   number of arguments
        char      **argv        I   list of arguments
        instr     input     O   structure variable for inputs

----------------------------------------------------------------------------*/
int msl12_input(int argc, char *argv[], char* progName, instr *input, filehandle *l1file) {
    /* hold all of the command line options */
    clo_optionList_t* list;

    list = clo_createList();

    /* initialize the option list with descriptions and default values */
    l2gen_init_options(list, progName);


    return msl12_option_input(argc, argv, list, NULL, input, l1file);

}


/* This function takes a predefined L1 file handle and loads all defaults    */

/* It's used by MSl1info, MSll2snpx, etc which don't use standatd par files. */
int msl12_input_defaults(filehandle *l1file, instr *input) {
    int argc = 0;
    char *argv[10];
    static char resolutionStr[FILENAME_MAX];
    static char ifileStr[FILENAME_MAX];
    static char geofileStr[FILENAME_MAX];

    argv[argc++] = "msl12";

    sprintf(ifileStr, "ifile=%s", l1file->name);
    argv[argc++] = ifileStr;

    if (l1file->geofile) {
        sprintf(geofileStr, "geofile=%s", l1file->geofile);
        argv[argc++] = geofileStr;
        argc = 3;
    }

    if (input->resolution != -1) {
        sprintf(resolutionStr, "resolution=%d", input->resolution);
        argv[argc++] = resolutionStr;
    }

    if (msl12_input(argc, argv, "msl12", input, l1file))
        return (-1);

    return 0;
}

int l2gen_usage(char *prog) {
    int i;
    clo_optionList_t* list;
    clo_option_t* option;

    list = clo_createList();
    l2gen_init_options(list, prog);
    clo_printUsage(list);

    return 0;
}
